diff options
author | Anatol Belski <ab@php.net> | 2014-10-10 22:51:13 +0200 |
---|---|---|
committer | Anatol Belski <ab@php.net> | 2014-10-10 22:51:13 +0200 |
commit | e1cd0e0a38deb91d24ded68df010b7f6c03d2cb6 (patch) | |
tree | 19090152884f17ee4d7691ee79462f4a0537d356 | |
parent | fe42847799c9fab9476ca6399e25ed0da0cb2d5c (diff) | |
parent | e33e4b2d8c44fb04afc54f688ed44dce7e8a2e0f (diff) | |
download | php-git-e1cd0e0a38deb91d24ded68df010b7f6c03d2cb6.tar.gz |
Merge remote-tracking branch 'origin/master' into native-tls
* origin/master: (40 commits)
int to size_t where the underlaying API supports it
use php_socket_t instead of int
fix signed/unsigned mismatch warning
fix compilation warning
Improved specialisation $this variable accessed through IS_UNUSED operand must be IS_OBJECT, so we don't have to check for its type or perform dereference.
Add notes about get_class_entry/get_class_name to UPGRADING
Fix casts in GD
Drop redundant casting code from ext/filter
update NEWS
update NEWS
update NEWS
update NEWS
Added note to UPGRADING regarding 64-bit support in pack()/unpack()
pack(): Use SIZEOF_ZEND_LONG instead of SIZEOF_LONG
Add 64 bit formats to pack() and unpack()
Help to CPU branch predictor
Removed unused EG(orig_error_reporting)
Update get_class_name semantics
Remove Z_OBJ_CLASS_NAME_P
Improved VM stack primitives for fast paths. Slow paths are not inlined anymore.
...
68 files changed, 2341 insertions, 2150 deletions
diff --git a/EXTENSIONS b/EXTENSIONS index 757a1a8fd6..00a78ec163 100644 --- a/EXTENSIONS +++ b/EXTENSIONS @@ -421,6 +421,12 @@ PRIMARY MAINTAINER: Derick Rethans <derick@derickrethans.nl> MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- +EXTENSION: opcache +PRIMARY MAINTAINER: Dmitry Stogov <dmitry@zend.com>, Xinchen Hui <laruence@php.net> +MAINTENANCE: Maintained +STATUS: Working +SINCE: 5.5.0 +------------------------------------------------------------------------------- EXTENSION: openssl PRIMARY MAINTAINER: Wez Furlong <wez@php.net>, Pierre-Alain Joye <pajoye@php.net> MAINTENANCE: Maintained @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 20??, PHP 7.0.0 +-Fileinfo: + . Fixed bug #66242 (libmagic: don't assume char is signed). (ArdB) + - CLI server: . Refactor MIME type handling to use a hash table instead of linear search. (Adam) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index aa6ee9b152..92cebc8db3 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -3,10 +3,6 @@ $Id$ PHP 7.0 INTERNALS UPGRADE NOTES 1. Internal API changes - a. Addition of do_operation and compare object handlers - b. return_value_ptr now always available, RETVAL_ZVAL_FAST macros - c. POST data handling - d. Arginfo changes e. New data types f. zend_parse_parameters() specs g. sprintf() formats @@ -104,6 +100,16 @@ PHP 7.0 INTERNALS UPGRADE NOTES - SIZEOF_ZEND_LONG reworked SIZEOF_ZEND_LONG representing the size of zend_long datatype - ZEND_SIZE_MAX Max value of size_t + k. The get_class_entry object handler is no longer available. Instead + zend_object.ce is always used. + + l. The get_class_name object handler is now only used for displaying class + names in debugging functions like var_dump(). It is no longer used in + get_class(), get_parent_class() or similar. + + The handler is now obligatory, no longer accepts a `parent` argument and + must return a non-NULL zend_string*, which will be released by the caller. + ======================== 2. Build system changes ======================== diff --git a/Zend/tests/bug68191.phpt b/Zend/tests/bug68191.phpt new file mode 100644 index 0000000000..198c5c7dce --- /dev/null +++ b/Zend/tests/bug68191.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #68191: Broken reference across objects +--FILE-- +<?php + +$obj = new stdClass; + +$obj->prop1 = 'abc'; +$obj->prop2 =& $obj->prop1; +$obj->prop2 .= 'xyz'; +var_dump($obj->prop1); + +$obj->prop3 = 1; +$obj->prop4 =& $obj->prop3; +++$obj->prop4; +var_dump($obj->prop3); + +?> +--EXPECT-- +string(6) "abcxyz" +int(2) diff --git a/Zend/zend.c b/Zend/zend.c index 36f8589409..a7d3bc156e 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -264,19 +264,10 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) /* {{{ */ case IS_OBJECT: { HashTable *properties = NULL; - zend_string *class_name = NULL; + zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr) TSRMLS_CC); + zend_printf("%s Object (", class_name->val); + zend_string_release(class_name); - if (Z_OBJ_HANDLER_P(expr, get_class_name)) { - class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr), 0 TSRMLS_CC); - } - if (class_name) { - zend_printf("%s Object (", class_name->val); - } else { - zend_printf("%s Object (", "Unknown Class"); - } - if (class_name) { - zend_string_release(class_name); - } if (Z_OBJ_HANDLER_P(expr, get_properties)) { properties = Z_OBJPROP_P(expr); } @@ -325,21 +316,13 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int case IS_OBJECT: { HashTable *properties; - zend_string *class_name = NULL; int is_temp; - if (Z_OBJ_HANDLER_P(expr, get_class_name)) { - class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr), 0 TSRMLS_CC); - } - if (class_name) { - ZEND_PUTS_EX(class_name->val); - } else { - ZEND_PUTS_EX("Unknown Class"); - } + zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr) TSRMLS_CC); + ZEND_PUTS_EX(class_name->val); + zend_string_release(class_name); + ZEND_PUTS_EX(" Object\n"); - if (class_name) { - zend_string_release(class_name); - } if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) { break; } diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 82864f2a46..5fa509bc6f 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -194,32 +194,6 @@ ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */ } /* }}} */ -ZEND_API zend_class_entry *zend_get_class_entry(const zend_object *zobject TSRMLS_DC) /* {{{ */ -{ - if (zobject->handlers->get_class_entry) { - return zobject->handlers->get_class_entry(zobject TSRMLS_CC); - } else { - zend_error(E_ERROR, "Class entry requested for an object without PHP class"); - return NULL; - } -} -/* }}} */ - -/* returns 1 if you need to copy result, 0 if it's already a copy */ -ZEND_API zend_string *zend_get_object_classname(const zend_object *object TSRMLS_DC) /* {{{ */ -{ - zend_string *ret; - - if (object->handlers->get_class_name != NULL) { - ret = object->handlers->get_class_name(object, 0 TSRMLS_CC); - if (ret) { - return ret; - } - } - return zend_get_class_entry(object TSRMLS_CC)->name; -} -/* }}} */ - static int parse_arg_object_to_string(zval *arg, char **p, size_t *pl, int type TSRMLS_DC) /* {{{ */ { if (Z_OBJ_HANDLER_P(arg, cast_object)) { @@ -2896,7 +2870,7 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache fcc->object = Z_OBJ(EG(current_execute_data)->This); fcc->called_scope = Z_OBJCE(EG(current_execute_data)->This); } else { - fcc->called_scope = fcc->object ? zend_get_class_entry(fcc->object TSRMLS_CC) : fcc->calling_scope; + fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope; } *strict_class = 1; ret = 1; @@ -3039,7 +3013,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca ((fcc->object && fcc->calling_scope->__call) || (!fcc->object && fcc->calling_scope->__callstatic)))) { if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) { - if (!zend_check_private(fcc->function_handler, fcc->object ? zend_get_class_entry(fcc->object TSRMLS_CC) : EG(scope), lmname TSRMLS_CC)) { + if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname TSRMLS_CC)) { retval = 0; fcc->function_handler = NULL; goto get_function_via_handler; @@ -3096,7 +3070,6 @@ get_function_via_handler: retval = 1; call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0; if (call_via_handler && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) && - Z_OBJ_HT(EG(current_execute_data)->This)->get_class_entry && instanceof_function(Z_OBJCE(EG(current_execute_data)->This), fcc->calling_scope TSRMLS_CC)) { fcc->object = Z_OBJ(EG(current_execute_data)->This); } @@ -3150,7 +3123,7 @@ get_function_via_handler: } if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) { if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) { - if (!zend_check_private(fcc->function_handler, fcc->object ? zend_get_class_entry(fcc->object TSRMLS_CC) : EG(scope), lmname TSRMLS_CC)) { + if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname TSRMLS_CC)) { if (error) { if (*error) { efree(*error); @@ -3183,7 +3156,7 @@ get_function_via_handler: zend_string_release(mname); if (fcc->object) { - fcc->called_scope = zend_get_class_entry(fcc->object TSRMLS_CC); + fcc->called_scope = fcc->object->ce; } if (retval) { fcc->initialized = 1; @@ -3224,7 +3197,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint case IS_STRING: if (object) { fcc->object = object; - fcc->calling_scope = zend_get_class_entry(object TSRMLS_CC); + fcc->calling_scope = object->ce; if (callable_name) { char *ptr; @@ -3822,8 +3795,7 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const EG(scope) = scope; if (!Z_OBJ_HT_P(object)->write_property) { - zend_string *class_name = zend_get_object_classname(Z_OBJ_P(object) TSRMLS_CC); - zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name->val); + zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, Z_OBJCE_P(object)->name->val); } ZVAL_STRINGL(&property, name, name_length); Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL TSRMLS_CC); @@ -4002,8 +3974,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const c EG(scope) = scope; if (!Z_OBJ_HT_P(object)->read_property) { - zend_string *class_name = zend_get_object_classname(Z_OBJ_P(object) TSRMLS_CC); - zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name->val); + zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, Z_OBJCE_P(object)->name->val); } ZVAL_STRINGL(&property, name, name_length); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 730e1b9e14..b73dcd4c65 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -339,8 +339,6 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const c ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, int name_length, zend_bool silent TSRMLS_DC); -ZEND_API zend_class_entry *zend_get_class_entry(const zend_object *object TSRMLS_DC); -ZEND_API zend_string *zend_get_object_classname(const zend_object *object TSRMLS_DC); ZEND_API char *zend_get_type_by_const(int type); #define getThis() (Z_OBJ(EX(This)) ? &EX(This) : NULL) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 9d567b47b7..9487bb6c1e 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -811,7 +811,7 @@ ZEND_FUNCTION(get_class) } } - RETURN_STR(zend_get_object_classname(Z_OBJ_P(obj) TSRMLS_CC)); + RETURN_STR(zend_string_copy(Z_OBJCE_P(obj)->name)); } /* }}} */ @@ -838,7 +838,6 @@ ZEND_FUNCTION(get_parent_class) { zval *arg; zend_class_entry *ce = NULL; - zend_string *name; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arg) == FAILURE) { return; @@ -854,12 +853,7 @@ ZEND_FUNCTION(get_parent_class) } if (Z_TYPE_P(arg) == IS_OBJECT) { - if (Z_OBJ_HT_P(arg)->get_class_name - && (name = Z_OBJ_HT_P(arg)->get_class_name(Z_OBJ_P(arg), 1 TSRMLS_CC)) != NULL) { - RETURN_STR(name); - } else { - ce = zend_get_class_entry(Z_OBJ_P(arg) TSRMLS_CC); - } + ce = Z_OBJ_P(arg)->ce; } else if (Z_TYPE_P(arg) == IS_STRING) { ce = zend_lookup_class(Z_STR_P(arg) TSRMLS_CC); } @@ -905,7 +899,7 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) /* if (!instance_ce) { RETURN_FALSE; } - } else if (Z_TYPE_P(obj) == IS_OBJECT && HAS_CLASS_ENTRY(*obj)) { + } else if (Z_TYPE_P(obj) == IS_OBJECT) { instance_ce = Z_OBJCE_P(obj); } else { RETURN_FALSE; @@ -1089,10 +1083,6 @@ ZEND_FUNCTION(get_class_methods) } if (Z_TYPE_P(klass) == IS_OBJECT) { - /* TBI!! new object handlers */ - if (!HAS_CLASS_ENTRY(*klass)) { - RETURN_FALSE; - } ce = Z_OBJCE_P(klass); } else if (Z_TYPE_P(klass) == IS_STRING) { ce = zend_lookup_class(Z_STR_P(klass) TSRMLS_CC); @@ -2185,9 +2175,7 @@ ZEND_FUNCTION(debug_print_backtrace) function_name = (func->common.scope && func->common.scope->trait_aliases) ? zend_resolve_method_name( - (object ? - zend_get_class_entry(object TSRMLS_CC) : - func->common.scope), func)->val : + (object ? object->ce : func->common.scope), func)->val : (func->common.function_name ? func->common.function_name->val : NULL); } else { @@ -2200,7 +2188,7 @@ ZEND_FUNCTION(debug_print_backtrace) if (func->common.scope) { class_name = func->common.scope->name; } else { - class_name = zend_get_object_classname(object TSRMLS_CC); + class_name = object->ce->name; } call_type = "->"; @@ -2307,7 +2295,6 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int zend_function *func; const char *function_name; const char *filename; - zend_string *class_name; const char *include_filename = NULL; zval stack_frame; @@ -2407,9 +2394,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int function_name = (func->common.scope && func->common.scope->trait_aliases) ? zend_resolve_method_name( - (object ? - zend_get_class_entry(object TSRMLS_CC) : - func->common.scope), func)->val : + (object ? object->ce : func->common.scope), func)->val : (func->common.function_name ? func->common.function_name->val : NULL); } else { @@ -2424,8 +2409,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int if (func->common.scope) { add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(func->common.scope->name)); } else { - class_name = zend_get_object_classname(object TSRMLS_CC); - add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(class_name)); + add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(object->ce->name)); } if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) { diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 90d7a6bb86..e4827f83b7 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -140,7 +140,7 @@ ZEND_METHOD(Closure, bind) } if (scope_arg != NULL) { /* scope argument was given */ - if (IS_ZEND_STD_OBJECT(*scope_arg)) { + if (Z_TYPE_P(scope_arg) == IS_OBJECT) { ce = Z_OBJCE_P(scope_arg); } else if (Z_TYPE_P(scope_arg) == IS_NULL) { ce = NULL; diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 6e4ee2fd30..f9c1a509a6 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -89,11 +89,8 @@ ZEND_API void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */ { #ifdef HAVE_DTRACE if (DTRACE_EXCEPTION_THROWN_ENABLED()) { - zend_string *classname; - if (exception != NULL) { - classname = zend_get_object_classname(Z_OBJ_P(exception) TSRMLS_CC); - DTRACE_EXCEPTION_THROWN(classname->val); + DTRACE_EXCEPTION_THROWN(Z_OBJ_P(exception)->ce->val); } else { DTRACE_EXCEPTION_THROWN(NULL); } @@ -452,7 +449,7 @@ static void _build_trace_args(zval *arg, smart_str *str TSRMLS_DC) /* {{{ */ break; case IS_OBJECT: smart_str_appends(str, "Object("); - smart_str_append(str, zend_get_object_classname(Z_OBJ_P(arg) TSRMLS_CC)); + smart_str_append(str, Z_OBJCE_P(arg)->name); smart_str_appends(str, "), "); break; } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 7348dda822..a3f18b960f 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -123,6 +123,61 @@ 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))) +#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, uint32_t var) { return EX_VAR(var); @@ -646,49 +701,50 @@ static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t ar } } -static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *property_name, int value_type, const 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 (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (UNEXPECTED(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 (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 (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; } } @@ -1246,31 +1302,30 @@ 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 (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { - if (UNEXPECTED(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 && - 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; + /* 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 (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) { @@ -1370,11 +1425,11 @@ ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_val 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 */ @@ -1610,11 +1665,13 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data 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( + 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, @@ -1662,12 +1719,10 @@ static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op 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 * sizeof(zval) 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); @@ -1681,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); } @@ -1697,8 +1752,8 @@ 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, 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); } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 9c620864dd..95421191f0 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -98,24 +98,22 @@ again: result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); break; case IS_OBJECT: - if (IS_ZEND_STD_OBJECT(*op)) { - if (Z_OBJ_HT_P(op)->cast_object) { - zval tmp; - if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL TSRMLS_CC) == SUCCESS) { - result = Z_TYPE(tmp) == IS_TRUE; - break; - } - zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", Z_OBJ_P(op)->ce->name->val); - } else if (Z_OBJ_HT_P(op)->get) { - zval rv; - zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv TSRMLS_CC); - if (Z_TYPE_P(tmp) != IS_OBJECT) { - /* for safety - avoid loop */ - convert_to_boolean(tmp); - result = Z_TYPE_P(tmp) == IS_TRUE; - zval_ptr_dtor(tmp); - break; - } + if (Z_OBJ_HT_P(op)->cast_object) { + zval tmp; + if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL TSRMLS_CC) == SUCCESS) { + result = Z_TYPE(tmp) == IS_TRUE; + break; + } + zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", Z_OBJ_P(op)->ce->name->val); + } else if (Z_OBJ_HT_P(op)->get) { + zval rv; + zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv TSRMLS_CC); + if (Z_TYPE_P(tmp) != IS_OBJECT) { + /* for safety - avoid loop */ + convert_to_boolean(tmp); + result = Z_TYPE_P(tmp) == IS_TRUE; + zval_ptr_dtor(tmp); + break; } } result = 1; @@ -137,10 +135,6 @@ ZEND_API int zval_update_constant_no_inline_change(zval *pp, zend_class_entry *s ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC); /* dedicated Zend executor functions - do not use! */ -#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)) - struct _zend_vm_stack { zval *top; zval *end; @@ -150,58 +144,21 @@ struct _zend_vm_stack { #define ZEND_VM_STACK_HEADER_SLOTS \ ((ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(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) - #define ZEND_VM_STACK_ELEMETS(stack) \ (((zval*)(stack)) + ZEND_VM_STACK_HEADER_SLOTS) -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; -} - -static zend_always_inline void zend_vm_stack_init(TSRMLS_D) -{ - EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE, NULL); - EG(argument_stack)->top++; -} - -static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D) -{ - zend_vm_stack stack = EG(argument_stack); - - while (stack != NULL) { - zend_vm_stack p = stack->prev; - efree(stack); - stack = p; - } -} - -static zend_always_inline void zend_vm_stack_extend(size_t size TSRMLS_DC) -{ - EG(argument_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), - EG(argument_stack)); -} +ZEND_API void zend_vm_stack_init(TSRMLS_D); +ZEND_API void zend_vm_stack_destroy(TSRMLS_D); +ZEND_API void* zend_vm_stack_extend(size_t size TSRMLS_DC); static zend_always_inline zval* zend_vm_stack_alloc(size_t size TSRMLS_DC) { - char *top = (char*)EG(argument_stack)->top; + char *top = (char*)EG(vm_stack_top); - if (UNEXPECTED(size > (size_t)(((char*)EG(argument_stack)->end) - top))) { - zend_vm_stack_extend(size TSRMLS_CC); - top = (char*)EG(argument_stack)->top; + if (UNEXPECTED(size > (size_t)(((char*)EG(vm_stack_end)) - top))) { + return (zval*)zend_vm_stack_extend(size TSRMLS_CC); } - EG(argument_stack)->top = (zval*)(top + size); + EG(vm_stack_top) = (zval*)(top + size); return (zval*)top; } @@ -254,12 +211,16 @@ static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call T static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *call TSRMLS_DC) { - zend_vm_stack p = EG(argument_stack); + zend_vm_stack p = EG(vm_stack); if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(p) == (zval*)call)) { - EG(argument_stack) = p->prev; + zend_vm_stack prev = p->prev; + + EG(vm_stack_top) = prev->top; + EG(vm_stack_end) = prev->end; + EG(vm_stack) = prev; efree(p); } else { - p->top = (zval*)call; + EG(vm_stack_top) = (zval*)call; } } @@ -286,11 +247,6 @@ void zend_shutdown_timeout_thread(void); #define WM_UNREGISTER_ZEND_TIMEOUT (WM_USER+2) #endif -/* The following tries to resolve the classname of a zval of type object. - * Since it is slow it should be only used in error messages. - */ -#define Z_OBJ_CLASS_NAME_P(obj) (((obj) && (obj)->handlers->get_class_entry != NULL && (obj)->handlers->get_class_entry) ? (obj)->handlers->get_class_entry(obj TSRMLS_CC)->name->val : "") - ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, uint32_t var); #define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */ @@ -314,7 +270,7 @@ ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_e ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS); -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); void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC); #define CACHED_PTR(num) \ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index e31f131781..2ec9c8dbcc 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -518,7 +518,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas } else if (Z_TYPE_P(p) == IS_CONSTANT) { int refcount; - SEPARATE_ZVAL_IF_NOT_REF(p); + SEPARATE_ZVAL_NOREF(p); MARK_CONSTANT_VISITED(p); refcount = Z_REFCOUNTED_P(p) ? Z_REFCOUNT_P(p) : 1; const_value = zend_get_constant_ex(Z_STR_P(p), scope, Z_CONST_FLAGS_P(p) TSRMLS_CC); @@ -596,7 +596,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount); } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) { zval tmp; - SEPARATE_ZVAL_IF_NOT_REF(p); + SEPARATE_ZVAL_NOREF(p); zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope TSRMLS_CC); if (inline_change) { diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 6ffd264a1d..c0d087fd99 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -217,8 +217,9 @@ ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array zend_generator *generator; zend_execute_data *current_execute_data; zend_execute_data *execute_data; - zend_vm_stack current_stack = EG(argument_stack); + zend_vm_stack current_stack = EG(vm_stack); + current_stack->top = EG(vm_stack_top); /* Create a clone of closure, because it may be destroyed */ if (op_array->fn_flags & ZEND_ACC_CLOSURE) { zend_op_array *op_array_copy = (zend_op_array*)emalloc(sizeof(zend_op_array)); @@ -259,8 +260,11 @@ ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array generator = (zend_generator *) Z_OBJ_P(return_value); execute_data->prev_execute_data = NULL; generator->execute_data = execute_data; - generator->stack = EG(argument_stack); - EG(argument_stack) = current_stack; + generator->stack = EG(vm_stack); + generator->stack->top = EG(vm_stack_top); + EG(vm_stack_top) = current_stack->top; + EG(vm_stack_end) = current_stack->end; + EG(vm_stack) = current_stack; /* EX(return_value) keeps pointer to zend_object (not a real zval) */ execute_data->return_value = (zval*)generator; @@ -293,12 +297,15 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ /* Backup executor globals */ zend_execute_data *original_execute_data = EG(current_execute_data); zend_class_entry *original_scope = EG(scope); - zend_vm_stack original_stack = EG(argument_stack); + zend_vm_stack original_stack = EG(vm_stack); + original_stack->top = EG(vm_stack_top); /* Set executor globals */ EG(current_execute_data) = generator->execute_data; EG(scope) = generator->execute_data->scope; - EG(argument_stack) = generator->stack; + EG(vm_stack_top) = generator->stack->top; + EG(vm_stack_end) = generator->stack->end; + EG(vm_stack) = generator->stack; /* We want the backtrace to look as if the generator function was * called from whatever method we are current running (e.g. next()). @@ -319,7 +326,9 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ /* Restore executor globals */ EG(current_execute_data) = original_execute_data; EG(scope) = original_scope; - EG(argument_stack) = original_stack; + EG(vm_stack_top) = original_stack->top; + EG(vm_stack_end) = original_stack->end; + EG(vm_stack) = original_stack; /* If an exception was thrown in the generator we have to internally * rethrow it in the parent scope. */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 8a42fbe1f2..43abffd1ce 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -164,13 +164,17 @@ struct _zend_executor_globals { JMP_BUF *bailout; int error_reporting; - int orig_error_reporting; int exit_status; HashTable *function_table; /* function symbol table */ HashTable *class_table; /* class table */ HashTable *zend_constants; /* constants table */ + zval *vm_stack_top; + zval *vm_stack_end; + zend_vm_stack vm_stack; + + struct _zend_execute_data *current_execute_data; zend_class_entry *scope; zend_long precision; @@ -192,8 +196,6 @@ struct _zend_executor_globals { HashTable regular_list; HashTable persistent_list; - zend_vm_stack argument_stack; - int user_error_handler_error_reporting; zval user_error_handler; zval user_exception_handler; @@ -218,8 +220,6 @@ struct _zend_executor_globals { const zend_op *opline_before_exception; zend_op exception_op[3]; - struct _zend_execute_data *current_execute_data; - struct _zend_module_entry *current_module; zend_property_info std_property_info; diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 97b89e926c..aaa677943d 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -275,7 +275,7 @@ static zend_always_inline int zend_hash_exists_ind(const HashTable *ht, zend_str } -static zend_always_inline zval *zend_hash_str_find_ind(const HashTable *ht, const char *str, int len) +static zend_always_inline zval *zend_hash_str_find_ind(const HashTable *ht, const char *str, size_t len) { zval *zv; @@ -368,7 +368,7 @@ static zend_always_inline int zend_symtable_exists(HashTable *ht, zend_string *k } -static zend_always_inline zval *zend_symtable_str_update(HashTable *ht, const char *str, int len, zval *pData) +static zend_always_inline zval *zend_symtable_str_update(HashTable *ht, const char *str, size_t len, zval *pData) { zend_ulong idx; @@ -380,7 +380,7 @@ static zend_always_inline zval *zend_symtable_str_update(HashTable *ht, const ch } -static zend_always_inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str, int len, zval *pData) +static zend_always_inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData) { zend_ulong idx; @@ -392,7 +392,7 @@ static zend_always_inline zval *zend_symtable_str_update_ind(HashTable *ht, cons } -static zend_always_inline int zend_symtable_str_del(HashTable *ht, const char *str, int len) +static zend_always_inline int zend_symtable_str_del(HashTable *ht, const char *str, size_t len) { zend_ulong idx; @@ -404,7 +404,7 @@ static zend_always_inline int zend_symtable_str_del(HashTable *ht, const char *s } -static zend_always_inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, int len) +static zend_always_inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, size_t len) { zend_ulong idx; @@ -416,7 +416,7 @@ static zend_always_inline int zend_symtable_str_del_ind(HashTable *ht, const cha } -static zend_always_inline zval *zend_symtable_str_find(HashTable *ht, const char *str, int len) +static zend_always_inline zval *zend_symtable_str_find(HashTable *ht, const char *str, size_t len) { zend_ulong idx; @@ -428,7 +428,7 @@ static zend_always_inline zval *zend_symtable_str_find(HashTable *ht, const char } -static zend_always_inline int zend_symtable_str_exists(HashTable *ht, const char *str, int len) +static zend_always_inline int zend_symtable_str_exists(HashTable *ht, const char *str, size_t len) { zend_ulong idx; @@ -457,7 +457,7 @@ static zend_always_inline void *zend_hash_add_new_ptr(HashTable *ht, zend_string return zv ? Z_PTR_P(zv) : NULL; } -static zend_always_inline void *zend_hash_str_add_ptr(HashTable *ht, const char *str, int len, void *pData) +static zend_always_inline void *zend_hash_str_add_ptr(HashTable *ht, const char *str, size_t len, void *pData) { zval tmp, *zv; @@ -475,7 +475,7 @@ static zend_always_inline void *zend_hash_update_ptr(HashTable *ht, zend_string return zv ? Z_PTR_P(zv) : NULL; } -static zend_always_inline void *zend_hash_str_update_ptr(HashTable *ht, const char *str, int len, void *pData) +static zend_always_inline void *zend_hash_str_update_ptr(HashTable *ht, const char *str, size_t len, void *pData) { zval tmp, *zv; @@ -497,7 +497,7 @@ static zend_always_inline void *zend_hash_add_mem(HashTable *ht, zend_string *ke return NULL; } -static zend_always_inline void *zend_hash_str_add_mem(HashTable *ht, const char *str, int len, void *pData, size_t size) +static zend_always_inline void *zend_hash_str_add_mem(HashTable *ht, const char *str, size_t len, void *pData, size_t size) { zval tmp, *zv; @@ -519,7 +519,7 @@ static zend_always_inline void *zend_hash_update_mem(HashTable *ht, zend_string return zend_hash_update_ptr(ht, key, p); } -static zend_always_inline void *zend_hash_str_update_mem(HashTable *ht, const char *str, int len, void *pData, size_t size) +static zend_always_inline void *zend_hash_str_update_mem(HashTable *ht, const char *str, size_t len, void *pData, size_t size) { void *p; @@ -576,7 +576,7 @@ static zend_always_inline void *zend_hash_find_ptr(const HashTable *ht, zend_str return zv ? Z_PTR_P(zv) : NULL; } -static zend_always_inline void *zend_hash_str_find_ptr(const HashTable *ht, const char *str, int len) +static zend_always_inline void *zend_hash_str_find_ptr(const HashTable *ht, const char *str, size_t len) { zval *zv; @@ -592,7 +592,7 @@ static zend_always_inline void *zend_hash_index_find_ptr(const HashTable *ht, ze return zv ? Z_PTR_P(zv) : NULL; } -static zend_always_inline void *zend_symtable_str_find_ptr(HashTable *ht, const char *str, int len) +static zend_always_inline void *zend_symtable_str_find_ptr(HashTable *ht, const char *str, size_t len) { zend_ulong idx; diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 26507ad23b..e299741000 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -282,8 +282,7 @@ ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *c zend_class_entry *ce_it; zend_user_it_new_iterator(ce, object, &iterator TSRMLS_CC); - ce_it = (Z_TYPE(iterator) == IS_OBJECT && - Z_OBJ_HT(iterator)->get_class_entry) ? Z_OBJCE(iterator) : NULL; + ce_it = (Z_TYPE(iterator) == IS_OBJECT) ? Z_OBJCE(iterator) : NULL; if (!ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && Z_OBJ(iterator) == Z_OBJ_P(object))) { if (!EG(exception)) { diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c index c2f51c4dd6..8edd5dbdc4 100644 --- a/Zend/zend_iterators.c +++ b/Zend/zend_iterators.c @@ -47,7 +47,6 @@ static zend_object_handlers iterator_object_handlers = { NULL, /* method get */ NULL, /* call */ NULL, /* get ctor */ - NULL, /* get_ce */ NULL, /* get class name */ NULL, /* compare */ NULL, /* cast */ diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 02c2b10268..6679cb1e46 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1089,7 +1089,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str /* Ensure that if we're calling a private function, we're allowed to do so. * If we're not and __call() handler exists, invoke it, otherwise error out. */ - updated_fbc = zend_check_private_int(fbc, zobj->handlers->get_class_entry(zobj TSRMLS_CC), lc_method_name TSRMLS_CC); + updated_fbc = zend_check_private_int(fbc, zobj->ce, lc_method_name TSRMLS_CC); if (EXPECTED(updated_fbc != NULL)) { fbc = updated_fbc; } else { @@ -1230,7 +1230,6 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st } if (ce->__call && Z_OBJ(EG(current_execute_data)->This) && - Z_OBJ_HT(EG(current_execute_data)->This)->get_class_entry && instanceof_function(Z_OBJCE(EG(current_execute_data)->This), ce TSRMLS_CC)) { return zend_get_user_call_function(ce, function_name); } else if (ce->__callstatic) { @@ -1526,26 +1525,9 @@ exit: } /* }}} */ -zend_class_entry *zend_std_object_get_class(const zend_object *object TSRMLS_DC) /* {{{ */ +zend_string *zend_std_object_get_class_name(const zend_object *zobj TSRMLS_DC) /* {{{ */ { - return object->ce; -} -/* }}} */ - -zend_string* zend_std_object_get_class_name(const zend_object *zobj, int parent TSRMLS_DC) /* {{{ */ -{ - zend_class_entry *ce; - - if (parent) { - if (!zobj->ce->parent) { - return NULL; - } - ce = zobj->ce->parent; - } else { - ce = zobj->ce; - } - - return zend_string_copy(ce->name); + return zend_string_copy(zobj->ce->name); } /* }}} */ @@ -1661,7 +1643,6 @@ ZEND_API zend_object_handlers std_object_handlers = { zend_std_get_method, /* get_method */ NULL, /* call_method */ zend_std_get_constructor, /* get_constructor */ - zend_std_object_get_class, /* get_class_entry */ zend_std_object_get_class_name, /* get_class_name */ zend_std_compare_objects, /* compare_objects */ zend_std_cast_object_tostring, /* cast_object */ diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index bc8500c3ec..2b06ebdf3d 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -95,8 +95,10 @@ typedef void (*zend_object_dtor_obj_t)(zend_object *object TSRMLS_DC); typedef void (*zend_object_free_obj_t)(zend_object *object TSRMLS_DC); typedef zend_object* (*zend_object_clone_obj_t)(zval *object TSRMLS_DC); -typedef zend_class_entry *(*zend_object_get_class_entry_t)(const zend_object *object TSRMLS_DC); -typedef zend_string *(*zend_object_get_class_name_t)(const zend_object *object, int parent TSRMLS_DC); +/* Get class name for display in var_dump and other debugging functions. + * Must be defined and must return a non-NULL value. */ +typedef zend_string *(*zend_object_get_class_name_t)(const zend_object *object TSRMLS_DC); + typedef int (*zend_object_compare_t)(zval *object1, zval *object2 TSRMLS_DC); typedef int (*zend_object_compare_zvals_t)(zval *resul, zval *op1, zval *op2 TSRMLS_DC); @@ -137,7 +139,6 @@ struct _zend_object_handlers { zend_object_get_method_t get_method; zend_object_call_method_t call_method; zend_object_get_constructor_t get_constructor; - zend_object_get_class_entry_t get_class_entry; zend_object_get_class_name_t get_class_name; zend_object_compare_t compare_objects; zend_object_cast_t cast_object; @@ -166,10 +167,6 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC); ZEND_API void rebuild_object_properties(zend_object *zobj); - -#define IS_ZEND_STD_OBJECT(z) (Z_TYPE(z) == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL)) -#define HAS_CLASS_ENTRY(z) (Z_OBJ_HT(z)->get_class_entry != NULL) - ZEND_API int zend_check_private(union _zend_function *fbc, zend_class_entry *ce, zend_string *function_name TSRMLS_DC); ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope); diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 50930df20d..04dd82b6a0 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -219,107 +219,11 @@ ZEND_API void zend_object_store_ctor_failed(zend_object *obj TSRMLS_DC) GC_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED; } -/* Proxy objects workings */ -typedef struct _zend_proxy_object { - zend_object std; - zval object; - zval property; -} zend_proxy_object; - -static zend_object_handlers zend_object_proxy_handlers; - -ZEND_API void zend_objects_proxy_destroy(zend_object *object TSRMLS_DC) -{ -} - -ZEND_API void zend_objects_proxy_free_storage(zend_proxy_object *object TSRMLS_DC) -{ - zval_ptr_dtor(&object->object); - zval_ptr_dtor(&object->property); - efree(object); -} - -ZEND_API void zend_objects_proxy_clone(zend_proxy_object *object, zend_proxy_object **object_clone TSRMLS_DC) -{ - *object_clone = emalloc(sizeof(zend_proxy_object)); - (*object_clone)->object = object->object; - (*object_clone)->property = object->property; - Z_ADDREF_P(&(*object_clone)->property); - Z_ADDREF_P(&(*object_clone)->object); -} - -ZEND_API zend_object *zend_object_create_proxy(zval *object, zval *member TSRMLS_DC) -{ - zend_proxy_object *obj = emalloc(sizeof(zend_proxy_object)); - - GC_REFCOUNT(obj) = 1; - GC_TYPE_INFO(obj) = IS_OBJECT; - obj->std.ce = NULL; - obj->std.properties = NULL; - obj->std.guards = NULL; - obj->std.handlers = &zend_object_proxy_handlers; - - ZVAL_COPY(&obj->object, object); - ZVAL_DUP(&obj->property, member); - - return (zend_object*)obj; -} - -ZEND_API void zend_object_proxy_set(zval *property, zval *value TSRMLS_DC) -{ - zend_proxy_object *probj = (zend_proxy_object*)Z_OBJ_P(property); - - if (Z_OBJ_HT(probj->object) && Z_OBJ_HT(probj->object)->write_property) { - Z_OBJ_HT(probj->object)->write_property(&probj->object, &probj->property, value, NULL TSRMLS_CC); - } else { - zend_error(E_WARNING, "Cannot write property of object - no write handler defined"); - } -} - -ZEND_API zval* zend_object_proxy_get(zval *property, zval *rv TSRMLS_DC) -{ - zend_proxy_object *probj = (zend_proxy_object*)Z_OBJ_P(property); - - if (Z_OBJ_HT(probj->object) && Z_OBJ_HT(probj->object)->read_property) { - return Z_OBJ_HT(probj->object)->read_property(&probj->object, &probj->property, BP_VAR_R, NULL, rv TSRMLS_CC); - } else { - zend_error(E_WARNING, "Cannot read property of object - no read handler defined"); - } - - return NULL; -} - ZEND_API zend_object_handlers *zend_get_std_object_handlers(void) { return &std_object_handlers; } -static zend_object_handlers zend_object_proxy_handlers = { - ZEND_OBJECTS_STORE_HANDLERS, - - NULL, /* read_property */ - NULL, /* write_property */ - NULL, /* read dimension */ - NULL, /* write_dimension */ - NULL, /* get_property_ptr_ptr */ - zend_object_proxy_get, /* get */ - zend_object_proxy_set, /* set */ - NULL, /* has_property */ - NULL, /* unset_property */ - NULL, /* has_dimension */ - NULL, /* unset_dimension */ - NULL, /* get_properties */ - NULL, /* get_method */ - NULL, /* call_method */ - NULL, /* get_constructor */ - NULL, /* get_class_entry */ - NULL, /* get_class_name */ - NULL, /* compare_objects */ - NULL, /* cast_object */ - NULL, /* count_elements */ -}; - - /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_types.h b/Zend/zend_types.h index b7e806804f..e3818dd2a1 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -438,7 +438,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define Z_OBJ_HANDLE(zval) (Z_OBJ((zval)))->handle #define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*(zval_p)) -#define Z_OBJCE(zval) zend_get_class_entry(Z_OBJ(zval) TSRMLS_CC) +#define Z_OBJCE(zval) (Z_OBJ(zval)->ce) #define Z_OBJCE_P(zval_p) Z_OBJCE(*(zval_p)) #define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC) @@ -783,6 +783,7 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) { #define SEPARATE_ZVAL_NOREF(zv) do { \ zval *_zv = (zv); \ + ZEND_ASSERT(Z_TYPE_P(_zv) != IS_REFERENCE); \ if (Z_COPYABLE_P(_zv) || \ Z_IMMUTABLE_P(_zv)) { \ if (Z_REFCOUNT_P(_zv) > 1) { \ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6aeac0e2d1..736ce178d6 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -339,11 +339,13 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (OP1_TYPE != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP2(); FREE_OP(free_op_data1); @@ -357,7 +359,8 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -432,7 +435,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (OP1_TYPE == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (OP1_TYPE == IS_VAR && !OP1_FREE) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -696,9 +699,11 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR| zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (OP1_TYPE != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); FREE_OP2(); if (RETURN_VALUE_USED(opline)) { @@ -788,9 +793,11 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (OP1_TYPE != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); FREE_OP2(); ZVAL_NULL(retval); @@ -1346,7 +1353,7 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) container = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_R); offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -1382,7 +1389,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV) zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -1406,7 +1413,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -1428,7 +1435,7 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV container = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_IS); offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -1468,7 +1475,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP| if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -1494,7 +1501,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -1551,7 +1558,7 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, OP1_TYPE, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); FREE_OP2(); FREE_OP1_VAR_PTR(); /* assign_obj has two opcodes! */ @@ -1579,7 +1586,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) zend_free_op free_op2; zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, OP1_TYPE, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); FREE_OP2(); } else { zend_free_op free_op2, free_op_data1, free_op_data2; @@ -2138,7 +2145,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) object = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -2184,10 +2191,10 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (OP2_TYPE != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -2197,7 +2204,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (OP2_TYPE == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -2207,7 +2214,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -2296,7 +2303,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -2309,8 +2316,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -2469,7 +2475,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -2941,7 +2947,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV) CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), catch_ce); } - ce = zend_get_class_entry(EG(exception) TSRMLS_CC); + ce = EG(exception)->ce; #ifdef HAVE_DTRACE if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) { @@ -3725,7 +3731,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY) obj = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_R); if (OP1_TYPE == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -4312,71 +4318,66 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV) } offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); ZEND_VM_C_LABEL(offset_again): - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); ZEND_VM_C_LABEL(num_index_dim): - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (OP2_TYPE != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - ZEND_VM_C_GOTO(num_index_dim); - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (OP2_TYPE != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + ZEND_VM_C_GOTO(num_index_dim); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - ZEND_VM_C_GOTO(num_index_dim); - case IS_TRUE: - hval = 1; - ZEND_VM_C_GOTO(num_index_dim); - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - ZEND_VM_C_GOTO(num_index_dim); - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - ZEND_VM_C_GOTO(offset_again); - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - FREE_OP2(); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + ZEND_VM_C_GOTO(num_index_dim); + case IS_TRUE: + hval = 1; + ZEND_VM_C_GOTO(num_index_dim); + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + ZEND_VM_C_GOTO(num_index_dim); + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + ZEND_VM_C_GOTO(offset_again); + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (OP2_TYPE == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - FREE_OP2(); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - FREE_OP2(); - break; + FREE_OP2(); + } else if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (OP2_TYPE == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + FREE_OP2(); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + FREE_OP2(); } FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); @@ -4398,7 +4399,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) offset = GET_OP2_ZVAL_PTR(BP_VAR_R); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (OP1_TYPE == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -4435,13 +4436,8 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) } if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { - zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } - ce = Z_OBJCE_P(array_ptr); - if (!ce || ce->get_iterator == NULL) { + if (ce->get_iterator == NULL) { Z_ADDREF_P(array_ptr); } array_ref = array_ptr; @@ -4465,7 +4461,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) } } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); - if (!ce || !ce->get_iterator) { + if (!ce->get_iterator) { if (OP1_TYPE == IS_CV) { Z_ADDREF_P(array_ref); } @@ -4938,7 +4934,7 @@ ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST| container = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_IS); offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (OP1_TYPE != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -4991,7 +4987,7 @@ ZEND_VM_C_LABEL(num_index_prop): } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (OP1_TYPE == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -5051,7 +5047,7 @@ ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST container = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_IS); offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (OP1_TYPE == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -5341,7 +5337,7 @@ ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMP|VAR|CV, ANY) SAVE_OPLINE(); expr = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { + if (Z_TYPE_P(expr) == IS_OBJECT) { result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); } else { result = 0; @@ -5976,16 +5972,12 @@ ZEND_VM_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|VAR|CV, ANY) break; case IS_OBJECT: if (Z_TYPE_P(value) == opline->extended_value) { - if (Z_OBJ_HT_P(value)->get_class_entry == NULL) { - ZVAL_TRUE(EX_VAR(opline->result.var)); + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); } else { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } + ZVAL_TRUE(EX_VAR(opline->result.var)); } } else { ZVAL_FALSE(EX_VAR(opline->result.var)); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index e68cf1945c..af0cd96bbf 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1613,7 +1613,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -1950,7 +1950,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -2136,7 +2136,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -2359,7 +2359,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -2782,7 +2782,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS obj = opline->op1.zv; if (IS_CONST == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -3082,13 +3082,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { - zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } - ce = Z_OBJCE_P(array_ptr); - if (!ce || ce->get_iterator == NULL) { + if (ce->get_iterator == NULL) { Z_ADDREF_P(array_ptr); } array_ref = array_ptr; @@ -3112,7 +3107,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); - if (!ce || !ce->get_iterator) { + if (!ce->get_iterator) { if (IS_CONST == IS_CV) { Z_ADDREF_P(array_ref); } @@ -3426,16 +3421,12 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER break; case IS_OBJECT: if (Z_TYPE_P(value) == opline->extended_value) { - if (Z_OBJ_HT_P(value)->get_class_entry == NULL) { - ZVAL_TRUE(EX_VAR(opline->result.var)); + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); } else { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } + ZVAL_TRUE(EX_VAR(opline->result.var)); } } else { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -3977,7 +3968,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_ container = opline->op1.zv; offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -4009,7 +4000,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE container = opline->op1.zv; offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -4048,7 +4039,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -4167,7 +4158,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -4180,8 +4171,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -4669,7 +4659,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER(ZE container = opline->op1.zv; offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CONST != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -4722,7 +4712,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_CONST == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -4781,7 +4771,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER(Z container = opline->op1.zv; offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CONST == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -5331,7 +5321,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HA container = opline->op1.zv; offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -5364,7 +5354,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_H container = opline->op1.zv; offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -5404,7 +5394,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OP if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -5490,7 +5480,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -5503,8 +5493,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -5744,7 +5733,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMP_HANDLER(ZEND container = opline->op1.zv; offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CONST != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -5797,7 +5786,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_CONST == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -5857,7 +5846,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMP_HANDLER(ZEN container = opline->op1.zv; offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CONST == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -6526,7 +6515,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HA container = opline->op1.zv; offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -6559,7 +6548,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_H container = opline->op1.zv; offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -6599,7 +6588,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OP if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -6685,7 +6674,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -6698,8 +6687,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -7093,7 +7081,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_VAR_HANDLER(ZEND container = opline->op1.zv; offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CONST != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -7146,7 +7134,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_CONST == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -7206,7 +7194,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_VAR_HANDLER(ZEN container = opline->op1.zv; offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CONST == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -7631,7 +7619,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -7644,8 +7632,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -8463,7 +8450,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAN container = opline->op1.zv; offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -8495,7 +8482,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HA container = opline->op1.zv; offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -8534,7 +8521,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -8620,7 +8607,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -8633,8 +8620,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -8745,7 +8731,7 @@ static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), catch_ce); } - ce = zend_get_class_entry(EG(exception) TSRMLS_CC); + ce = EG(exception)->ce; #ifdef HAVE_DTRACE if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) { @@ -8925,7 +8911,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER(ZEND_ container = opline->op1.zv; offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CONST != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -8978,7 +8964,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_CONST == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -9037,7 +9023,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER(ZEND container = opline->op1.zv; offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CONST == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -9612,7 +9598,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) obj = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -9913,13 +9899,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG } if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { - zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } - ce = Z_OBJCE_P(array_ptr); - if (!ce || ce->get_iterator == NULL) { + if (ce->get_iterator == NULL) { Z_ADDREF_P(array_ptr); } array_ref = array_ptr; @@ -9943,7 +9924,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG } } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); - if (!ce || !ce->get_iterator) { + if (!ce->get_iterator) { if (IS_TMP_VAR == IS_CV) { Z_ADDREF_P(array_ref); } @@ -10222,7 +10203,7 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { + if (Z_TYPE_P(expr) == IS_OBJECT) { result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); } else { result = 0; @@ -10294,16 +10275,12 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A break; case IS_OBJECT: if (Z_TYPE_P(value) == opline->extended_value) { - if (Z_OBJ_HT_P(value)->get_class_entry == NULL) { - ZVAL_TRUE(EX_VAR(opline->result.var)); + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); } else { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } + ZVAL_TRUE(EX_VAR(opline->result.var)); } } else { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -10827,7 +10804,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -10859,7 +10836,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -10898,7 +10875,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -11006,7 +10983,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -11051,10 +11028,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CONST != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -11064,7 +11041,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -11074,7 +11051,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -11389,7 +11366,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CONST_HANDLER(ZEND container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_TMP_VAR != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -11442,7 +11419,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_TMP_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -11501,7 +11478,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CONST_HANDLER(ZEN container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_TMP_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -12018,7 +11995,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -12051,7 +12028,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -12091,7 +12068,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -12172,7 +12149,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -12217,10 +12194,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_TMP_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -12230,7 +12207,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_TMP_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -12240,7 +12217,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -12403,7 +12380,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMP_HANDLER(ZEND_O container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_TMP_VAR != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -12456,7 +12433,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_TMP_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -12516,7 +12493,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMP_HANDLER(ZEND_ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_TMP_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -13185,7 +13162,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -13218,7 +13195,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -13258,7 +13235,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -13339,7 +13316,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -13384,10 +13361,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -13397,7 +13374,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -13407,7 +13384,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -13724,7 +13701,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_O container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_TMP_VAR != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -13777,7 +13754,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_TMP_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -13837,7 +13814,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_TMP_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -14944,7 +14921,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -14976,7 +14953,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -15015,7 +14992,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -15095,7 +15072,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -15140,10 +15117,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CV != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -15153,7 +15130,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -15163,7 +15140,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -15324,7 +15301,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CV_HANDLER(ZEND_OP container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_TMP_VAR != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -15377,7 +15354,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_TMP_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -15436,7 +15413,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CV_HANDLER(ZEND_O container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_TMP_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -16342,7 +16319,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) obj = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -16644,13 +16621,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG } if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { - zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } - ce = Z_OBJCE_P(array_ptr); - if (!ce || ce->get_iterator == NULL) { + if (ce->get_iterator == NULL) { Z_ADDREF_P(array_ptr); } array_ref = array_ptr; @@ -16674,7 +16646,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG } } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); - if (!ce || !ce->get_iterator) { + if (!ce->get_iterator) { if (IS_VAR == IS_CV) { Z_ADDREF_P(array_ref); } @@ -17181,7 +17153,7 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { + if (Z_TYPE_P(expr) == IS_OBJECT) { result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); } else { result = 0; @@ -17253,16 +17225,12 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A break; case IS_OBJECT: if (Z_TYPE_P(value) == opline->extended_value) { - if (Z_OBJ_HT_P(value)->get_class_entry == NULL) { - ZVAL_TRUE(EX_VAR(opline->result.var)); + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); } else { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } + ZVAL_TRUE(EX_VAR(opline->result.var)); } } else { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -17571,11 +17539,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -17589,7 +17559,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -17663,7 +17634,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -17927,9 +17898,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -18018,9 +17991,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -18385,7 +18360,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -18420,7 +18395,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18444,7 +18419,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18466,7 +18441,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -18505,7 +18480,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18531,7 +18506,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18588,7 +18563,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_obj has two opcodes! */ @@ -18616,7 +18591,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN zval *property_name = opline->op2.zv; - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { zend_free_op free_op_data1, free_op_data2; @@ -18712,7 +18687,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -18758,10 +18733,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CONST != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -18771,7 +18746,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -18781,7 +18756,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -18869,7 +18844,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -18882,8 +18857,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -19245,71 +19219,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND } offset = opline->op2.zv; - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CONST == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CONST == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -19331,7 +19300,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND offset = opline->op2.zv; ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -19436,7 +19405,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CONST_HANDLER(ZEND container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_VAR != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -19489,7 +19458,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -19548,7 +19517,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEN container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -20007,11 +19976,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); @@ -20025,7 +19996,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -20100,7 +20072,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -20364,9 +20336,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { @@ -20456,9 +20430,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); @@ -20673,7 +20649,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -20709,7 +20685,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -20733,7 +20709,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -20755,7 +20731,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -20795,7 +20771,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -20821,7 +20797,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -20845,7 +20821,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_obj has two opcodes! */ @@ -20873,7 +20849,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL zend_free_op free_op2; zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); } else { zend_free_op free_op2, free_op_data1, free_op_data2; @@ -20969,7 +20945,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -21015,10 +20991,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_TMP_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -21028,7 +21004,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_TMP_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -21038,7 +21014,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -21127,7 +21103,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -21140,8 +21116,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -21333,71 +21308,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE } offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_TMP_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_TMP_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_ptr_dtor_nogc(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_TMP_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -21419,7 +21389,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -21445,7 +21415,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_O container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_VAR != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -21498,7 +21468,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -21558,7 +21528,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_ container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -22018,11 +21988,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); @@ -22036,7 +22008,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -22111,7 +22084,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -22375,9 +22348,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { @@ -22467,9 +22442,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); @@ -22835,7 +22812,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -22871,7 +22848,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22895,7 +22872,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22917,7 +22894,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -22957,7 +22934,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22983,7 +22960,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -23007,7 +22984,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_obj has two opcodes! */ @@ -23035,7 +23012,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zend_free_op free_op2; zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); } else { zend_free_op free_op2, free_op_data1, free_op_data2; @@ -23195,7 +23172,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -23241,10 +23218,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -23254,7 +23231,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -23264,7 +23241,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -23353,7 +23330,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -23366,8 +23343,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -23634,71 +23610,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_ptr_dtor_nogc(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -23720,7 +23691,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -23825,7 +23796,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_O container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_VAR != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -23878,7 +23849,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -23938,7 +23909,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_ container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -24123,11 +24094,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -24141,7 +24114,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -24215,7 +24189,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (* container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -24714,7 +24688,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA zval *property_name = NULL; - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { zend_free_op free_op_data1, free_op_data2; @@ -24827,7 +24801,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -24840,8 +24814,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -25594,11 +25567,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -25612,7 +25587,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -25686,7 +25662,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -25950,9 +25926,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -26041,9 +26019,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -26257,7 +26237,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -26292,7 +26272,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26316,7 +26296,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26338,7 +26318,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -26377,7 +26357,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26403,7 +26383,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26427,7 +26407,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_obj has two opcodes! */ @@ -26455,7 +26435,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { zend_free_op free_op_data1, free_op_data2; @@ -26613,7 +26593,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -26659,10 +26639,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CV != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -26672,7 +26652,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -26682,7 +26662,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -26770,7 +26750,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (Z_OBJ(EX(This)) && zend_get_class_entry(Z_OBJ(EX(This)) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -26783,8 +26763,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ GC_REFCOUNT(object)++; } if (!object || - (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC))) { + !instanceof_function(object->ce, ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -26975,71 +26954,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CV == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CV == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -27061,7 +27035,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -27087,7 +27061,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OP container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_VAR != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -27140,7 +27114,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -27199,7 +27173,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CV_HANDLER(ZEND_O container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -27383,7 +27357,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG obj = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -27463,11 +27437,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -27481,7 +27457,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -27554,7 +27531,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -27818,9 +27795,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -27909,9 +27888,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -27990,7 +27971,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -28025,7 +28006,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -28049,7 +28030,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -28071,7 +28052,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -28110,7 +28091,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -28136,7 +28117,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OP if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -28160,7 +28141,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); /* assign_obj has two opcodes! */ @@ -28231,7 +28212,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -28276,10 +28257,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CONST != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -28289,7 +28270,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -28299,7 +28280,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -28459,71 +28440,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H } offset = opline->op2.zv; - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CONST == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CONST == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } CHECK_EXCEPTION(); @@ -28545,7 +28521,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H offset = opline->op2.zv; ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -28571,7 +28547,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER(Z container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_UNUSED != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -28624,7 +28600,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -28683,7 +28659,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER( container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -28851,11 +28827,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); @@ -28869,7 +28847,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -28943,7 +28922,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (* container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -29207,9 +29186,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { @@ -29299,9 +29280,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); @@ -29381,7 +29364,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -29417,7 +29400,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -29441,7 +29424,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -29463,7 +29446,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -29503,7 +29486,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -29529,7 +29512,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCO if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -29553,7 +29536,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); /* assign_obj has two opcodes! */ @@ -29630,7 +29613,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -29675,10 +29658,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_TMP_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -29688,7 +29671,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_TMP_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -29698,7 +29681,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -29763,71 +29746,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN } offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_TMP_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_TMP_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_ptr_dtor_nogc(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_TMP_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } CHECK_EXCEPTION(); @@ -29849,7 +29827,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -29875,7 +29853,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEN container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_UNUSED != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -29928,7 +29906,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -29988,7 +29966,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMP_HANDLER(ZE container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -30157,11 +30135,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); @@ -30175,7 +30155,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -30249,7 +30230,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (* container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -30513,9 +30494,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { @@ -30605,9 +30588,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); @@ -30687,7 +30672,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -30723,7 +30708,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30747,7 +30732,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30769,7 +30754,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -30809,7 +30794,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30835,7 +30820,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCO if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30859,7 +30844,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); /* assign_obj has two opcodes! */ @@ -30936,7 +30921,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -30981,10 +30966,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -30994,7 +30979,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -31004,7 +30989,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -31069,71 +31054,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_ptr_dtor_nogc(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } CHECK_EXCEPTION(); @@ -31155,7 +31135,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -31181,7 +31161,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEN container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_UNUSED != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -31234,7 +31214,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -31294,7 +31274,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_VAR_HANDLER(ZE container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -31463,11 +31443,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -31481,7 +31463,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -31554,7 +31537,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -31979,11 +31962,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -31997,7 +31982,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -32070,7 +32056,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -32334,9 +32320,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -32425,9 +32413,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -32506,7 +32496,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -32541,7 +32531,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32565,7 +32555,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32587,7 +32577,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -32626,7 +32616,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32652,7 +32642,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCOD if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32676,7 +32666,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); /* assign_obj has two opcodes! */ @@ -32752,7 +32742,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -32797,10 +32787,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CV != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -32810,7 +32800,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -32820,7 +32810,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -32884,71 +32874,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CV == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CV == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } CHECK_EXCEPTION(); @@ -32970,7 +32955,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -32996,7 +32981,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_UNUSED != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -33049,7 +33034,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -33108,7 +33093,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEN container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -33984,7 +33969,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) obj = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -34284,13 +34269,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS } if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { - zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } - ce = Z_OBJCE_P(array_ptr); - if (!ce || ce->get_iterator == NULL) { + if (ce->get_iterator == NULL) { Z_ADDREF_P(array_ptr); } array_ref = array_ptr; @@ -34314,7 +34294,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS } } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); - if (!ce || !ce->get_iterator) { + if (!ce->get_iterator) { if (IS_CV == IS_CV) { Z_ADDREF_P(array_ref); } @@ -34577,7 +34557,7 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { + if (Z_TYPE_P(expr) == IS_OBJECT) { result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); } else { result = 0; @@ -34649,16 +34629,12 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR break; case IS_OBJECT: if (Z_TYPE_P(value) == opline->extended_value) { - if (Z_OBJ_HT_P(value)->get_class_entry == NULL) { - ZVAL_TRUE(EX_VAR(opline->result.var)); + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); } else { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } + ZVAL_TRUE(EX_VAR(opline->result.var)); } } else { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -34967,11 +34943,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -34985,7 +34963,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -35058,7 +35037,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -35322,9 +35301,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -35413,9 +35394,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -35780,7 +35763,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -35815,7 +35798,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35839,7 +35822,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35861,7 +35844,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -35900,7 +35883,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35926,7 +35909,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35983,7 +35966,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); /* assign_obj has two opcodes! */ @@ -36011,7 +35994,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND zval *property_name = opline->op2.zv; - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { zend_free_op free_op_data1, free_op_data2; @@ -36107,7 +36090,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -36152,10 +36135,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CONST != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -36165,7 +36148,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -36175,7 +36158,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -36417,71 +36400,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL } offset = opline->op2.zv; - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CONST == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CONST == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } CHECK_EXCEPTION(); @@ -36503,7 +36481,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL offset = opline->op2.zv; ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -36608,7 +36586,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_ container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CV != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -36661,7 +36639,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -36720,7 +36698,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -37235,11 +37213,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); @@ -37253,7 +37233,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -37327,7 +37308,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -37591,9 +37572,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { @@ -37683,9 +37666,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); @@ -37900,7 +37885,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -37936,7 +37921,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -37960,7 +37945,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -37982,7 +37967,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -38022,7 +38007,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -38048,7 +38033,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -38072,7 +38057,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); /* assign_obj has two opcodes! */ @@ -38100,7 +38085,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE zend_free_op free_op2; zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); } else { zend_free_op free_op2, free_op_data1, free_op_data2; @@ -38196,7 +38181,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -38241,10 +38226,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_TMP_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -38254,7 +38239,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_TMP_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -38264,7 +38249,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -38433,71 +38418,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER } offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_TMP_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_TMP_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_ptr_dtor_nogc(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_TMP_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } CHECK_EXCEPTION(); @@ -38519,7 +38499,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -38545,7 +38525,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OP container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CV != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -38598,7 +38578,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -38658,7 +38638,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMP_HANDLER(ZEND_O container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -39117,11 +39097,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); @@ -39135,7 +39117,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -39209,7 +39192,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -39473,9 +39456,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { @@ -39565,9 +39550,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); @@ -39933,7 +39920,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -39969,7 +39956,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39993,7 +39980,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -40015,7 +40002,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -40055,7 +40042,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -40081,7 +40068,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -40105,7 +40092,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); /* assign_obj has two opcodes! */ @@ -40133,7 +40120,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zend_free_op free_op2; zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); } else { zend_free_op free_op2, free_op_data1, free_op_data2; @@ -40292,7 +40279,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -40337,10 +40324,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -40350,7 +40337,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -40360,7 +40347,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -40604,71 +40591,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_ptr_dtor_nogc(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } CHECK_EXCEPTION(); @@ -40690,7 +40672,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -40795,7 +40777,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OP container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CV != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -40848,7 +40830,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -40908,7 +40890,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_VAR_HANDLER(ZEND_O container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -41092,11 +41074,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -41110,7 +41094,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -41183,7 +41168,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -41682,7 +41667,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN zval *property_name = NULL; - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { zend_free_op free_op_data1, free_op_data2; @@ -42418,11 +42403,13 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -42436,7 +42423,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); have_get_ptr = 1; binary_op(zptr, zptr, value TSRMLS_CC); @@ -42509,7 +42497,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -42773,9 +42761,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -42864,9 +42854,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -43080,7 +43072,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -43115,7 +43107,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -43139,7 +43131,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -43161,7 +43153,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -43200,7 +43192,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -43226,7 +43218,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -43250,7 +43242,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); /* assign_obj has two opcodes! */ @@ -43278,7 +43270,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { zend_free_op free_op_data1, free_op_data2; @@ -43435,7 +43427,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { @@ -43480,10 +43472,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CV != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -43493,7 +43485,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -43503,7 +43495,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ @@ -43670,71 +43662,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CV == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CV == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } CHECK_EXCEPTION(); @@ -43756,7 +43743,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -43782,7 +43769,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPC container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CV != IS_UNUSED && Z_TYPE_P(container) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -43835,7 +43822,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { + } else if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_dimension) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -43894,7 +43881,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OP container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->has_property) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index 74a3920e34..6f63a1fbd8 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -423,14 +423,7 @@ static union _zend_function *com_constructor_get(zend_object *object TSRMLS_DC) } } -static zend_class_entry *com_class_entry_get(const zend_object *object TSRMLS_DC) -{ - php_com_dotnet_object *obj = (php_com_dotnet_object *)object; - - return obj->ce; -} - -static zend_string* com_class_name_get(const zend_object *object, int parent TSRMLS_DC) +static zend_string* com_class_name_get(const zend_object *object TSRMLS_DC) { php_com_dotnet_object *obj = (php_com_dotnet_object *)object; @@ -564,7 +557,6 @@ zend_object_handlers php_com_object_handlers = { com_method_get, com_call_method, com_constructor_get, - com_class_entry_get, com_class_name_get, com_objects_compare, com_object_cast, diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c index 881ebfbaea..ddee9bc179 100644 --- a/ext/com_dotnet/com_saproxy.c +++ b/ext/com_dotnet/com_saproxy.c @@ -333,12 +333,7 @@ static union _zend_function *saproxy_constructor_get(zend_object *object TSRMLS_ return NULL; } -static zend_class_entry *saproxy_class_entry_get(const zend_object *object TSRMLS_DC) -{ - return php_com_saproxy_class_entry; -} - -static zend_string* saproxy_class_name_get(const zend_object *object, int parent TSRMLS_DC) +static zend_string* saproxy_class_name_get(const zend_object *object TSRMLS_DC) { return zend_string_copy(php_com_saproxy_class_entry->name); } @@ -420,7 +415,6 @@ zend_object_handlers php_com_saproxy_handlers = { saproxy_method_get, saproxy_call_method, saproxy_constructor_get, - saproxy_class_entry_get, saproxy_class_name_get, saproxy_objects_compare, saproxy_object_cast, diff --git a/ext/dom/dom_properties.h b/ext/dom/dom_properties.h index 7e607f0a2e..b5c81d271b 100644 --- a/ext/dom/dom_properties.h +++ b/ext/dom/dom_properties.h @@ -137,6 +137,8 @@ int dom_node_text_content_write(dom_object *obj, zval *newval TSRMLS_DC); /* nodelist properties */ int dom_nodelist_length_read(dom_object *obj, zval *retval TSRMLS_DC); +xmlNodePtr dom_nodelist_xml_item(dom_nnodemap_object *objmap, long index); +xmlNodePtr dom_nodelist_baseobj_item(dom_nnodemap_object *objmap, long index); /* notation properties */ int dom_notation_public_id_read(dom_object *obj, zval *retval TSRMLS_DC); diff --git a/ext/dom/nodelist.c b/ext/dom/nodelist.c index 68292d1983..15071739d2 100644 --- a/ext/dom/nodelist.c +++ b/ext/dom/nodelist.c @@ -153,8 +153,7 @@ PHP_FUNCTION(dom_nodelist_item) } else { nodep = nodep->children; } - itemnode = dom_get_elements_by_tag_name_ns_raw( - nodep, (char *) objmap->ns, (char *) objmap->local, &count, index); + itemnode = dom_get_elements_by_tag_name_ns_raw(nodep, objmap->ns, objmap->local, &count, index); } } } diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 8a00ad5a08..71c06612db 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -619,6 +619,8 @@ PHP_MINIT_FUNCTION(dom) memcpy(&dom_nnodemap_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers)); dom_nnodemap_object_handlers.free_obj = dom_nnodemap_objects_free_storage; dom_nnodemap_object_handlers.dtor_obj = dom_nnodemap_object_dtor; + dom_nnodemap_object_handlers.read_dimension = dom_nodelist_read_dimension; + dom_nnodemap_object_handlers.has_dimension = dom_nodelist_has_dimension; zend_hash_init(&classes, 0, NULL, NULL, 1); @@ -1542,6 +1544,41 @@ xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName) { } /* }}} end dom_get_nsdecl */ +zval *dom_nodelist_read_dimension(zval *object, zval *offset, int type, zval *rv TSRMLS_DC) /* {{{ */ +{ + zval offset_copy; + + if (!offset) { + return NULL; + } + + ZVAL_COPY(&offset_copy, offset); + convert_to_long(&offset_copy); + + zend_call_method_with_1_params(object, Z_OBJCE_P(object), NULL, "item", rv, &offset_copy); + + return rv; +} /* }}} end dom_nodelist_read_dimension */ + +int dom_nodelist_has_dimension(zval *object, zval *member, int check_empty TSRMLS_DC) +{ + zval *length, offset_copy; + int ret; + + ZVAL_COPY(&offset_copy, member); + convert_to_long(&offset_copy); + + if (Z_LVAL(offset_copy) < 0) { + return 0; + } + + length = zend_read_property(Z_OBJCE_P(object), object, "length", sizeof("length") - 1, 0 TSRMLS_CC); + + ret = Z_LVAL(offset_copy) < Z_LVAL_P(length); + + return ret; +} /* }}} end dom_nodelist_has_dimension */ + #endif /* HAVE_DOM */ /* diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 9162031a90..02eb2d9509 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -126,6 +126,8 @@ xmlNode *php_dom_libxml_hash_iter(xmlHashTable *ht, int index); xmlNode *php_dom_libxml_notation_iter(xmlHashTable *ht, int index); zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); int dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce TSRMLS_DC); +zval *dom_nodelist_read_dimension(zval *object, zval *offset, int type, zval *rv TSRMLS_DC); +int dom_nodelist_has_dimension(zval *object, zval *member, int check_empty TSRMLS_DC); #define REGISTER_DOM_CLASS(ce, name, parent_ce, funcs, entry) \ INIT_CLASS_ENTRY(ce, name, funcs); \ diff --git a/ext/dom/tests/bug67949.phpt b/ext/dom/tests/bug67949.phpt new file mode 100644 index 0000000000..fc29881ca7 --- /dev/null +++ b/ext/dom/tests/bug67949.phpt @@ -0,0 +1,61 @@ +--TEST-- +Bug #67949: DOMNodeList elements should be accessible through array notation +--FILE-- +<?php + +$html = <<<HTML +<div>data</div> +<a href="test">hello world</a> +HTML; +$doc = new DOMDocument; +$doc->loadHTML($html); + +$nodes = $doc->getElementsByTagName('div'); + +echo "testing has_dimension\n"; +var_dump(isset($nodes[0])); +var_dump(isset($nodes[1])); +var_dump(isset($nodes[-1])); + +echo "testing property access\n"; +var_dump($nodes[0]->textContent); +var_dump($nodes[1]->textContent); + +echo "testing offset not a long\n"; +$offset = 'test'; +var_dump($offset); +var_dump($nodes[$offset]->textContent); +var_dump($offset); +var_dump(isset($nodes[$offset])); +var_dump($offset); + +echo "testing read_dimension with null offset\n"; +var_dump($nodes[][] = 1); + +echo "testing attribute access\n"; +$anchor = $doc->getElementsByTagName('a')[0]; +var_dump($anchor->attributes[0]->name); + +echo "==DONE==\n"; + +--EXPECTF-- +testing has_dimension +bool(true) +bool(false) +bool(false) +testing property access +string(4) "data" + +Notice: Trying to get property of non-object in %s on line %d +NULL +testing offset not a long +string(4) "test" +string(4) "data" +string(4) "test" +bool(true) +string(4) "test" +testing read_dimension with null offset +NULL +testing attribute access +string(4) "href" +==DONE== diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 7ef65bc196..530dce6f53 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -491,7 +491,8 @@ static void php_zval_filter_recursive(zval *value, zend_long filter, zend_long f } ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(value), element) { - SEPARATE_ZVAL_IF_NOT_REF(element); + ZVAL_DEREF(element); + SEPARATE_ZVAL_NOREF(element); if (Z_TYPE_P(element) == IS_ARRAY) { Z_ARRVAL_P(element)->u.v.nApplyCount++; php_zval_filter_recursive(element, filter, flags, options, charset, copy TSRMLS_CC); @@ -581,9 +582,7 @@ static void php_filter_call(zval *filtered, zend_long filter, zval *filter_args, char *charset = NULL; if (filter_args && Z_TYPE_P(filter_args) != IS_ARRAY) { - zend_long lval; - - PHP_FILTER_GET_LONG_OPT(filter_args, lval); + zend_long lval = zval_get_long(filter_args); if (filter != -1) { /* handler for array apply */ /* filter_args is the filter_flags */ @@ -597,11 +596,11 @@ static void php_filter_call(zval *filtered, zend_long filter, zval *filter_args, } } else if (filter_args) { if ((option = zend_hash_str_find(HASH_OF(filter_args), "filter", sizeof("filter") - 1)) != NULL) { - PHP_FILTER_GET_LONG_OPT(option, filter); + filter = zval_get_long(option); } if ((option = zend_hash_str_find(HASH_OF(filter_args), "flags", sizeof("flags") - 1)) != NULL) { - PHP_FILTER_GET_LONG_OPT(option, filter_flags); + filter_flags = zval_get_long(option); if (!(filter_flags & FILTER_REQUIRE_ARRAY || filter_flags & FILTER_FORCE_ARRAY)) { filter_flags |= FILTER_REQUIRE_SCALAR; @@ -661,7 +660,6 @@ static void php_filter_call(zval *filtered, zend_long filter, zval *filter_args, static void php_filter_array_handler(zval *input, zval *op, zval *return_value, zend_bool add_empty TSRMLS_DC) /* {{{ */ { - zend_ulong index; zend_string *arg_key; zval *tmp, *arg_elm; @@ -676,7 +674,7 @@ static void php_filter_array_handler(zval *input, zval *op, zval *return_value, } else if (Z_TYPE_P(op) == IS_ARRAY) { array_init(return_value); - ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(op), index, arg_key, arg_elm) { + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(op), arg_key, arg_elm) { if (arg_key == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Numeric keys are not allowed in the definition array"); zval_ptr_dtor(return_value); @@ -732,7 +730,7 @@ PHP_FUNCTION(filter_input) if (Z_TYPE_P(filter_args) == IS_LONG) { filter_flags = Z_LVAL_P(filter_args); } else if (Z_TYPE_P(filter_args) == IS_ARRAY && (option = zend_hash_str_find(HASH_OF(filter_args), "flags", sizeof("flags") - 1)) != NULL) { - PHP_FILTER_GET_LONG_OPT(option, filter_flags); + filter_flags = zval_get_long(option); } if (Z_TYPE_P(filter_args) == IS_ARRAY && (opt = zend_hash_str_find(HASH_OF(filter_args), "options", sizeof("options") - 1)) != NULL && @@ -809,7 +807,7 @@ PHP_FUNCTION(filter_input_array) if (Z_TYPE_P(op) == IS_LONG) { filter_flags = Z_LVAL_P(op); } else if (Z_TYPE_P(op) == IS_ARRAY && (option = zend_hash_str_find(HASH_OF(op), "flags", sizeof("flags") - 1)) != NULL) { - PHP_FILTER_GET_LONG_OPT(option, filter_flags); + filter_flags = zval_get_long(option); } } diff --git a/ext/filter/filter_private.h b/ext/filter/filter_private.h index 8c41d8811e..b07b6ca534 100644 --- a/ext/filter/filter_private.h +++ b/ext/filter/filter_private.h @@ -117,17 +117,6 @@ } \ } -#define PHP_FILTER_GET_LONG_OPT(zv, opt) { \ - if (Z_TYPE_P(zv) != IS_LONG) { \ - zval ___tmp; \ - ZVAL_DUP(&___tmp, zv); \ - convert_to_long(&___tmp); \ - opt = Z_LVAL(___tmp); \ - } else { \ - opt = Z_LVAL_P(zv); \ - } \ -} - #endif /* FILTER_PRIVATE_H */ /* diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index c37df628d2..b7c0b49a85 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -41,7 +41,7 @@ var_name##_set = 0; \ if (option_array) { \ if ((option_val = zend_hash_str_find(HASH_OF(option_array), option_name, sizeof(option_name) - 1)) != NULL) { \ - PHP_FILTER_GET_LONG_OPT(option_val, var_name); \ + var_name = zval_get_long(option_val); \ var_name##_set = 1; \ } \ } diff --git a/ext/filter/tests/filter_var_array_with_ref.phpt b/ext/filter/tests/filter_var_array_with_ref.phpt new file mode 100644 index 0000000000..cd202edf4d --- /dev/null +++ b/ext/filter/tests/filter_var_array_with_ref.phpt @@ -0,0 +1,23 @@ +--TEST-- +filter_var_array() on array with reference +--FILE-- +<?php + +$array = ["123foo"]; +$array2 = [&$array]; +var_dump(filter_var_array($array2, FILTER_VALIDATE_INT)); +var_dump($array); + +?> +--EXPECTF-- +array(1) { + [0]=> + &array(1) { + [0]=> + bool(false) + } +} +array(1) { + [0]=> + bool(false) +} diff --git a/ext/gd/gd.c b/ext/gd/gd.c index fe7ea1c4b1..c08f9d4271 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -1537,14 +1537,7 @@ PHP_FUNCTION(imagesetstyle) stylearr = safe_emalloc(sizeof(int), zend_hash_num_elements(HASH_OF(styles)), 0); ZEND_HASH_FOREACH_VAL(HASH_OF(styles), item) { - if (Z_TYPE_P(item) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, item); - convert_to_long(&lval); - stylearr[index++] = Z_LVAL(lval); - } else { - stylearr[index++] = Z_LVAL_P(item); - } + stylearr[index++] = zval_get_long(item); } ZEND_HASH_FOREACH_END(); gdImageSetStyle(im, stylearr, index); @@ -3354,24 +3347,10 @@ static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled) for (i = 0; i < npoints; i++) { if ((var = zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2))) != NULL) { - if (Z_TYPE_P(var) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, var); - convert_to_long(&lval); - points[i].x = Z_LVAL(lval); - } else { - points[i].x = Z_LVAL_P(var); - } + points[i].x = zval_get_long(var); } if ((var = zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2) + 1)) != NULL) { - if (Z_TYPE_P(var) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, var); - convert_to_long(&lval); - points[i].y = Z_LVAL(lval); - } else { - points[i].y = Z_LVAL_P(var); - } + points[i].y = zval_get_long(var); } } @@ -3842,9 +3821,8 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int continue; } if (strcmp("linespacing", key->val) == 0) { - convert_to_double_ex(item); strex.flags |= gdFTEX_LINESPACE; - strex.linespacing = Z_DVAL_P(item); + strex.linespacing = zval_get_double(item); } } ZEND_HASH_FOREACH_END(); } @@ -4871,15 +4849,8 @@ PHP_FUNCTION(imageconvolution) } for (j=0; j<3; j++) { - if ((var2 = zend_hash_index_find(Z_ARRVAL_P(var), (j))) != NULL) { - if (Z_TYPE_P(var2) != IS_DOUBLE) { - zval dval; - ZVAL_COPY(&dval, var2); - convert_to_double(&dval); - matrix[i][j] = (float)Z_DVAL(dval); - } else { - matrix[i][j] = (float)Z_DVAL_P(var2); - } + if ((var2 = zend_hash_index_find(Z_ARRVAL_P(var), j)) != NULL) { + matrix[i][j] = (float) zval_get_double(var2); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must have a 3x3 matrix"); RETURN_FALSE; @@ -4972,56 +4943,28 @@ PHP_FUNCTION(imagecrop) ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "x", sizeof("x") -1)) != NULL) { - if (Z_TYPE_P(tmp) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, tmp); - convert_to_long(&lval); - rect.x = Z_LVAL(lval); - } else { - rect.x = Z_LVAL_P(tmp); - } + rect.x = zval_get_long(tmp); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing x position"); RETURN_FALSE; } if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "y", sizeof("y") - 1)) != NULL) { - if (Z_TYPE_P(tmp) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, tmp); - convert_to_long(&lval); - rect.y = Z_LVAL(lval); - } else { - rect.y = Z_LVAL_P(tmp); - } + rect.y = zval_get_long(tmp); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position"); RETURN_FALSE; } if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "width", sizeof("width") - 1)) != NULL) { - if (Z_TYPE_P(tmp) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, tmp); - convert_to_long(&lval); - rect.width = Z_LVAL(lval); - } else { - rect.width = Z_LVAL_P(tmp); - } + rect.width = zval_get_long(tmp); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing width"); RETURN_FALSE; } if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "height", sizeof("height") - 1)) != NULL) { - if (Z_TYPE_P(tmp) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, tmp); - convert_to_long(&lval); - rect.height = Z_LVAL(lval); - } else { - rect.height = Z_LVAL_P(tmp); - } + rect.height = zval_get_long(tmp); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing height"); RETURN_FALSE; @@ -5154,12 +5097,7 @@ PHP_FUNCTION(imageaffine) affine[i] = Z_DVAL_P(zval_affine_elem); break; case IS_STRING: - { - zval dval; - ZVAL_COPY(&dval, zval_affine_elem); - convert_to_double(&dval); - affine[i] = Z_DVAL(dval); - } + affine[i] = zval_get_double(zval_affine_elem); break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i); @@ -5170,56 +5108,28 @@ PHP_FUNCTION(imageaffine) if (z_rect != NULL) { if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "x", sizeof("x") - 1)) != NULL) { - if (Z_TYPE_P(tmp) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, tmp); - convert_to_long(&lval); - rect.x = Z_LVAL(lval); - } else { - rect.x = Z_LVAL_P(tmp); - } + rect.x = zval_get_long(tmp); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing x position"); RETURN_FALSE; } if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "y", sizeof("y") - 1)) != NULL) { - if (Z_TYPE_P(tmp) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, tmp); - convert_to_long(&lval); - rect.y = Z_LVAL(lval); - } else { - rect.y = Z_LVAL_P(tmp); - } + rect.y = zval_get_long(tmp); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position"); RETURN_FALSE; } if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "width", sizeof("width") - 1)) != NULL) { - if (Z_TYPE_P(tmp) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, tmp); - convert_to_long(&lval); - rect.width = Z_LVAL(lval); - } else { - rect.width = Z_LVAL_P(tmp); - } + rect.width = zval_get_long(tmp); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing width"); RETURN_FALSE; } if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "height", sizeof("height") - 1)) != NULL) { - if (Z_TYPE_P(tmp) != IS_LONG) { - zval lval; - ZVAL_COPY(&lval, tmp); - convert_to_long(&lval); - rect.height = Z_LVAL(lval); - } else { - rect.height = Z_LVAL_P(tmp); - } + rect.height = zval_get_long(tmp); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing height"); RETURN_FALSE; @@ -5268,28 +5178,14 @@ PHP_FUNCTION(imageaffinematrixget) RETURN_FALSE; } if ((tmp = zend_hash_str_find(HASH_OF(options), "x", sizeof("x") - 1)) != NULL) { - if (Z_TYPE_P(tmp) != IS_DOUBLE) { - zval dval; - ZVAL_COPY(&dval, tmp); - convert_to_double(&dval); - x = Z_DVAL(dval); - } else { - x = Z_DVAL_P(tmp); - } + x = zval_get_double(tmp); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing x position"); RETURN_FALSE; } if ((tmp = zend_hash_str_find(HASH_OF(options), "y", sizeof("y") - 1)) != NULL) { - if (Z_TYPE_P(tmp) != IS_DOUBLE) { - zval dval; - ZVAL_COPY(&dval, tmp); - convert_to_double(&dval); - y = Z_DVAL(dval); - } else { - y = Z_DVAL_P(tmp); - } + y = zval_get_double(tmp); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position"); RETURN_FALSE; @@ -5312,8 +5208,8 @@ PHP_FUNCTION(imageaffinematrixget) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number is expected as option"); RETURN_FALSE; } - convert_to_double_ex(options); - angle = Z_DVAL_P(options); + + angle = zval_get_double(options); if (type == GD_AFFINE_SHEAR_HORIZONTAL) { res = gdAffineShearHorizontal(affine, angle); @@ -5372,12 +5268,7 @@ PHP_FUNCTION(imageaffinematrixconcat) m1[i] = Z_DVAL_P(tmp); break; case IS_STRING: - { - zval dval; - ZVAL_COPY(&dval, tmp); - convert_to_double(&dval); - m1[i] = Z_DVAL(dval); - } + m1[i] = zval_get_double(tmp); break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i); @@ -5393,12 +5284,7 @@ PHP_FUNCTION(imageaffinematrixconcat) m2[i] = Z_DVAL_P(tmp); break; case IS_STRING: - { - zval dval; - ZVAL_COPY(&dval, tmp); - convert_to_double(&dval); - m2[i] = Z_DVAL(dval); - } + m2[i] = zval_get_double(tmp); break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i); diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c index de0bc768ad..8be88c3fee 100644 --- a/ext/mbstring/php_mbregex.c +++ b/ext/mbstring/php_mbregex.c @@ -1343,8 +1343,7 @@ PHP_FUNCTION(mb_ereg_search_init) zval_ptr_dtor(&MBREX(search_str)); } - ZVAL_COPY(&MBREX(search_str), arg_str); - SEPARATE_ZVAL_IF_NOT_REF(&MBREX(search_str)); + ZVAL_DUP(&MBREX(search_str), arg_str); MBREX(search_pos) = 0; diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 1bd3734718..beab9be59c 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1171,10 +1171,6 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr return new_persistent_script; } - /* cleanup after calculation */ - new_persistent_script->mem = ZCG(mem); - new_persistent_script->size = memory_used; - /* Copy into shared memory */ new_persistent_script = zend_accel_script_persist(new_persistent_script, &key, key_length TSRMLS_CC); diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index c3c7285c48..28c3d21102 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -164,6 +164,8 @@ typedef struct _zend_persistent_script { void *mem; /* shared memory area used by script structures */ size_t size; /* size of used shared memory */ + void *arena_mem; /* part that should be copied into process */ + size_t arena_size; /* All entries that shouldn't be counted in the ADLER32 * checksum must be declared in this struct @@ -234,6 +236,8 @@ typedef struct _zend_accel_globals { time_t request_time; /* preallocated shared-memory block to save current script */ void *mem; + void *arena_mem; + zend_persistent_script *current_persistent_script; /* cache to save hash lookup on the same INCLUDE opcode */ const zend_op *cache_opline; zend_persistent_script *cache_persistent_script; diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index bae6121f7e..1d949e4db4 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -38,6 +38,9 @@ static uint32_t zend_accel_refcount = ZEND_PROTECTED_REFCOUNT; # define accel_xlat_get(old, new) ((new) = zend_hash_str_find_ptr(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (zend_ulong)(zend_uintptr_t)(old), (void**)&(new))) #endif +#define ARENA_REALLOC(ptr) \ + (void*)(((char*)(ptr)) + ((char*)ZCG(arena_mem) - (char*)ZCG(current_persistent_script)->arena_mem)) + typedef int (*id_function_t)(void *, void *); typedef void (*unique_copy_ctor_func_t)(void *pElement); @@ -467,9 +470,8 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class q->key = zend_clone_str(p->key TSRMLS_CC); /* Copy data */ - ZVAL_PTR(&q->val, (void *) zend_arena_alloc(&CG(arena), sizeof(zend_op_array))); + ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val))); new_entry = (zend_op_array*)Z_PTR(q->val); - *new_entry = *(zend_op_array*)Z_PTR(p->val); /* Copy constructor */ /* we use refcount to show that op_array is referenced from several places */ @@ -544,9 +546,8 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla q->key = zend_clone_str(p->key TSRMLS_CC); /* Copy data */ - ZVAL_PTR(&q->val, (void *) zend_arena_alloc(&CG(arena), sizeof(zend_property_info))); + ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val))); prop_info = Z_PTR(q->val); - *prop_info = *(zend_property_info*)Z_PTR(p->val); /* Copy constructor */ prop_info->name = zend_clone_str(prop_info->name TSRMLS_CC); @@ -604,8 +605,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce) zend_class_entry *new_ce; zend_function *new_func; - *pce = ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry)); - *ce = *old_ce; + *pce = ce = ARENA_REALLOC(old_ce); ce->refcount = 1; if (old_ce->refcount != 1) { @@ -796,8 +796,7 @@ static void zend_accel_function_hash_copy(HashTable *target, HashTable *source, } } if (pCopyConstructor) { - Z_PTR_P(t) = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); - memcpy(Z_PTR_P(t), Z_PTR(p->val), sizeof(zend_op_array)); + Z_PTR_P(t) = ARENA_REALLOC(Z_PTR(p->val)); pCopyConstructor(Z_PTR_P(t)); } } @@ -873,9 +872,16 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); *op_array = persistent_script->main_op_array; - if (from_shared_memory) { + if (EXPECTED(from_shared_memory)) { zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0); + ZCG(current_persistent_script) = persistent_script; + ZCG(arena_mem) = NULL; + if (EXPECTED(persistent_script->arena_size)) { + ZCG(arena_mem) = zend_arena_alloc(&CG(arena), persistent_script->arena_size); + memcpy(ZCG(arena_mem), persistent_script->arena_mem, persistent_script->arena_size); + } + /* Copy all the necessary stuff from shared memory to regular memory, and protect the shared script */ if (zend_hash_num_elements(&persistent_script->class_table) > 0) { zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor TSRMLS_CC); @@ -902,6 +908,7 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, } zend_hash_destroy(&ZCG(bind_hash)); + ZCG(current_persistent_script) = NULL; } else /* if (!from_shared_memory) */ { if (zend_hash_num_elements(&persistent_script->function_table) > 0) { zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table, NULL TSRMLS_CC); @@ -918,7 +925,7 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, CG(compiled_filename) = orig_compiled_filename; } - if (!from_shared_memory) { + if (UNEXPECTED(!from_shared_memory)) { free_persistent_script(persistent_script, 0); /* free only hashes */ } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 6491b9d781..3e91740a71 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -486,7 +486,10 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc static void zend_persist_op_array(zval *zv TSRMLS_DC) { - Z_PTR_P(zv) = zend_accel_memdup(Z_PTR_P(zv), sizeof(zend_op_array)); + memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_op_array)); + zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem)); + Z_PTR_P(zv) = ZCG(arena_mem); + ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_op_array))); zend_persist_op_array_ex(Z_PTR_P(zv), NULL TSRMLS_CC); } @@ -494,7 +497,10 @@ static void zend_persist_property_info(zval *zv TSRMLS_DC) { zend_property_info *prop; - prop = Z_PTR_P(zv) = zend_accel_memdup(Z_PTR_P(zv), sizeof(zend_property_info)); + memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_property_info)); + zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem)); + prop = Z_PTR_P(zv) = ZCG(arena_mem); + ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_property_info))); zend_accel_store_interned_string(prop->name); if (prop->doc_comment) { if (ZCG(accel_directives).save_comments) { @@ -514,7 +520,10 @@ static void zend_persist_class_entry(zval *zv TSRMLS_DC) zend_class_entry *ce = Z_PTR_P(zv); if (ce->type == ZEND_USER_CLASS) { - ce = Z_PTR_P(zv) = zend_accel_memdup(ce, sizeof(zend_class_entry)); + memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_entry)); + zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem)); + ce = Z_PTR_P(zv) = ZCG(arena_mem); + ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_entry))); zend_accel_store_interned_string(ce->name); zend_hash_persist(&ce->function_table, zend_persist_op_array TSRMLS_CC); if (ce->default_properties_table) { @@ -703,13 +712,20 @@ static void zend_accel_persist_class_table(HashTable *class_table TSRMLS_DC) zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length TSRMLS_DC) { + script->mem = ZCG(mem); + zend_shared_alloc_clear_xlat_table(); - zend_hash_persist(&script->function_table, zend_persist_op_array TSRMLS_CC); - zend_accel_persist_class_table(&script->class_table TSRMLS_CC); - zend_persist_op_array_ex(&script->main_op_array, script TSRMLS_CC); + + zend_accel_store(script, sizeof(zend_persistent_script)); *key = zend_accel_memdup(*key, key_length + 1); zend_accel_store_string(script->full_path); - zend_accel_store(script, sizeof(zend_persistent_script)); + + script->arena_mem = ZCG(arena_mem) = ZCG(mem); + ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size); + + zend_accel_persist_class_table(&script->class_table TSRMLS_CC); + zend_hash_persist(&script->function_table, zend_persist_op_array TSRMLS_CC); + zend_persist_op_array_ex(&script->main_op_array, script TSRMLS_CC); return script; } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index d2de94f05c..0a7b835648 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -26,10 +26,10 @@ #include "zend_shared_alloc.h" #include "zend_operators.h" -#define START_SIZE() uint memory_used = 0 -#define ADD_DUP_SIZE(m,s) memory_used += zend_shared_memdup_size((void*)m, s) -#define ADD_SIZE(m) memory_used += ZEND_ALIGNED_SIZE(m) -#define RETURN_SIZE() return memory_used +#define ADD_DUP_SIZE(m,s) ZCG(current_persistent_script)->size += zend_shared_memdup_size((void*)m, s) +#define ADD_SIZE(m) ZCG(current_persistent_script)->size += ZEND_ALIGNED_SIZE(m) + +#define ADD_ARENA_SIZE(m) ZCG(current_persistent_script)->arena_size += ZEND_ALIGNED_SIZE(m) # define ADD_STRING(str) \ ADD_DUP_SIZE((str), _STR_HEADER_SIZE + (str)->len + 1) @@ -47,16 +47,15 @@ } \ } while (0) -static uint zend_persist_zval_calc(zval *z TSRMLS_DC); +static void zend_persist_zval_calc(zval *z TSRMLS_DC); -static uint zend_hash_persist_calc(HashTable *ht, uint (*pPersistElement)(zval *pElement TSRMLS_DC) TSRMLS_DC) +static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval *pElement TSRMLS_DC) TSRMLS_DC) { uint idx; Bucket *p; - START_SIZE(); if (!ht->nTableMask) { - RETURN_SIZE(); + return; } if (ht->u.flags & HASH_FLAG_PACKED) { ADD_SIZE(sizeof(Bucket) * ht->nNumUsed); @@ -75,26 +74,23 @@ static uint zend_hash_persist_calc(HashTable *ht, uint (*pPersistElement)(zval * GC_FLAGS(p->key) |= flags; } - ADD_SIZE(pPersistElement(&p->val TSRMLS_CC)); + pPersistElement(&p->val TSRMLS_CC); } - - RETURN_SIZE(); } -static uint zend_persist_ast_calc(zend_ast *ast TSRMLS_DC) +static void zend_persist_ast_calc(zend_ast *ast TSRMLS_DC) { uint32_t i; - START_SIZE(); if (ast->kind == ZEND_AST_ZVAL) { ADD_SIZE(sizeof(zend_ast_zval)); - ADD_SIZE(zend_persist_zval_calc(zend_ast_get_zval(ast) TSRMLS_CC)); + zend_persist_zval_calc(zend_ast_get_zval(ast) TSRMLS_CC); } else if (zend_ast_is_list(ast)) { zend_ast_list *list = zend_ast_get_list(ast); ADD_SIZE(sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children); for (i = 0; i < list->children; i++) { if (list->child[i]) { - ADD_SIZE(zend_persist_ast_calc(list->child[i] TSRMLS_CC)); + zend_persist_ast_calc(list->child[i] TSRMLS_CC); } } } else { @@ -102,18 +98,16 @@ static uint zend_persist_ast_calc(zend_ast *ast TSRMLS_DC) ADD_SIZE(sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children); for (i = 0; i < children; i++) { if (ast->child[i]) { - ADD_SIZE(zend_persist_ast_calc(ast->child[i] TSRMLS_CC)); + zend_persist_ast_calc(ast->child[i] TSRMLS_CC); } } } - RETURN_SIZE(); } -static uint zend_persist_zval_calc(zval *z TSRMLS_DC) +static void zend_persist_zval_calc(zval *z TSRMLS_DC) { zend_uchar flags; uint size; - START_SIZE(); switch (Z_TYPE_P(z)) { case IS_STRING: @@ -129,38 +123,35 @@ static uint zend_persist_zval_calc(zval *z TSRMLS_DC) size = zend_shared_memdup_size(Z_ARR_P(z), sizeof(zend_array)); if (size) { ADD_SIZE(size); - ADD_SIZE(zend_hash_persist_calc(Z_ARRVAL_P(z), zend_persist_zval_calc TSRMLS_CC)); + zend_hash_persist_calc(Z_ARRVAL_P(z), zend_persist_zval_calc TSRMLS_CC); } break; case IS_REFERENCE: size = zend_shared_memdup_size(Z_REF_P(z), sizeof(zend_reference)); if (size) { ADD_SIZE(size); - ADD_SIZE(zend_persist_zval_calc(Z_REFVAL_P(z) TSRMLS_CC)); + zend_persist_zval_calc(Z_REFVAL_P(z) TSRMLS_CC); } break; case IS_CONSTANT_AST: size = zend_shared_memdup_size(Z_AST_P(z), sizeof(zend_ast_ref)); if (size) { ADD_SIZE(size); - ADD_SIZE(zend_persist_ast_calc(Z_ASTVAL_P(z) TSRMLS_CC)); + zend_persist_ast_calc(Z_ASTVAL_P(z) TSRMLS_CC); } break; } - RETURN_SIZE(); } -static uint zend_persist_op_array_calc_ex(zend_op_array *op_array TSRMLS_DC) +static void zend_persist_op_array_calc_ex(zend_op_array *op_array TSRMLS_DC) { - START_SIZE(); - if (op_array->type != ZEND_USER_FUNCTION) { - return 0; + return; } if (op_array->static_variables) { ADD_DUP_SIZE(op_array->static_variables, sizeof(HashTable)); - ADD_SIZE(zend_hash_persist_calc(op_array->static_variables, zend_persist_zval_calc TSRMLS_CC)); + zend_hash_persist_calc(op_array->static_variables, zend_persist_zval_calc TSRMLS_CC); } if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) { @@ -171,7 +162,7 @@ static uint zend_persist_op_array_calc_ex(zend_op_array *op_array TSRMLS_DC) op_array->function_name = new_name; } } - RETURN_SIZE(); + return; } if (op_array->literals) { @@ -179,7 +170,7 @@ static uint zend_persist_op_array_calc_ex(zend_op_array *op_array TSRMLS_DC) zval *end = p + op_array->last_literal; ADD_DUP_SIZE(op_array->literals, sizeof(zval) * op_array->last_literal); while (p < end) { - ADD_SIZE(zend_persist_zval_calc(p TSRMLS_CC)); + zend_persist_zval_calc(p TSRMLS_CC); p++; } } @@ -239,46 +230,39 @@ static uint zend_persist_op_array_calc_ex(zend_op_array *op_array TSRMLS_DC) ADD_INTERNED_STRING(op_array->vars[i], 0); } } - - RETURN_SIZE(); } -static uint zend_persist_op_array_calc(zval *zv TSRMLS_DC) +static void zend_persist_op_array_calc(zval *zv TSRMLS_DC) { - START_SIZE(); - ADD_SIZE(sizeof(zend_op_array)); - ADD_SIZE(zend_persist_op_array_calc_ex(Z_PTR_P(zv) TSRMLS_CC)); - RETURN_SIZE(); + ADD_ARENA_SIZE(sizeof(zend_op_array)); + zend_persist_op_array_calc_ex(Z_PTR_P(zv) TSRMLS_CC); } -static uint zend_persist_property_info_calc(zval *zv TSRMLS_DC) +static void zend_persist_property_info_calc(zval *zv TSRMLS_DC) { zend_property_info *prop = Z_PTR_P(zv); - START_SIZE(); - ADD_SIZE(sizeof(zend_property_info)); + ADD_ARENA_SIZE(sizeof(zend_property_info)); ADD_INTERNED_STRING(prop->name, 0); if (ZCG(accel_directives).save_comments && prop->doc_comment) { ADD_STRING(prop->doc_comment); } - RETURN_SIZE(); } -static uint zend_persist_class_entry_calc(zval *zv TSRMLS_DC) +static void zend_persist_class_entry_calc(zval *zv TSRMLS_DC) { zend_class_entry *ce = Z_PTR_P(zv); - START_SIZE(); if (ce->type == ZEND_USER_CLASS) { - ADD_DUP_SIZE(ce, sizeof(zend_class_entry)); + ADD_ARENA_SIZE(sizeof(zend_class_entry)); ADD_INTERNED_STRING(ce->name, 0); - ADD_SIZE(zend_hash_persist_calc(&ce->function_table, zend_persist_op_array_calc TSRMLS_CC)); + zend_hash_persist_calc(&ce->function_table, zend_persist_op_array_calc TSRMLS_CC); if (ce->default_properties_table) { int i; ADD_SIZE(sizeof(zval) * ce->default_properties_count); for (i = 0; i < ce->default_properties_count; i++) { - ADD_SIZE(zend_persist_zval_calc(&ce->default_properties_table[i] TSRMLS_CC)); + zend_persist_zval_calc(&ce->default_properties_table[i] TSRMLS_CC); } } if (ce->default_static_members_table) { @@ -286,10 +270,10 @@ static uint zend_persist_class_entry_calc(zval *zv TSRMLS_DC) ADD_SIZE(sizeof(zval) * ce->default_static_members_count); for (i = 0; i < ce->default_static_members_count; i++) { - ADD_SIZE(zend_persist_zval_calc(&ce->default_static_members_table[i] TSRMLS_CC)); + zend_persist_zval_calc(&ce->default_static_members_table[i] TSRMLS_CC); } } - ADD_SIZE(zend_hash_persist_calc(&ce->constants_table, zend_persist_zval_calc TSRMLS_CC)); + zend_hash_persist_calc(&ce->constants_table, zend_persist_zval_calc TSRMLS_CC); if (ZEND_CE_FILENAME(ce)) { ADD_STRING(ZEND_CE_FILENAME(ce)); @@ -298,7 +282,7 @@ static uint zend_persist_class_entry_calc(zval *zv TSRMLS_DC) ADD_STRING(ZEND_CE_DOC_COMMENT(ce)); } - ADD_SIZE(zend_hash_persist_calc(&ce->properties_info, zend_persist_property_info_calc TSRMLS_CC)); + zend_hash_persist_calc(&ce->properties_info, zend_persist_property_info_calc TSRMLS_CC); if (ce->trait_aliases) { int i = 0; @@ -345,24 +329,32 @@ static uint zend_persist_class_entry_calc(zval *zv TSRMLS_DC) ADD_SIZE(sizeof(zend_trait_precedence*) * (i + 1)); } } - RETURN_SIZE(); } -static uint zend_accel_persist_class_table_calc(HashTable *class_table TSRMLS_DC) +static void zend_accel_persist_class_table_calc(HashTable *class_table TSRMLS_DC) { - return zend_hash_persist_calc(class_table, zend_persist_class_entry_calc TSRMLS_CC); + zend_hash_persist_calc(class_table, zend_persist_class_entry_calc TSRMLS_CC); } uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_script, char *key, unsigned int key_length TSRMLS_DC) { - START_SIZE(); + new_persistent_script->mem = NULL; + new_persistent_script->size = 0; + new_persistent_script->arena_mem = NULL; + new_persistent_script->arena_size = 0; + ZCG(current_persistent_script) = new_persistent_script; - ADD_SIZE(zend_hash_persist_calc(&new_persistent_script->function_table, zend_persist_op_array_calc TSRMLS_CC)); - ADD_SIZE(zend_accel_persist_class_table_calc(&new_persistent_script->class_table TSRMLS_CC)); - ADD_SIZE(zend_persist_op_array_calc_ex(&new_persistent_script->main_op_array TSRMLS_CC)); + ADD_DUP_SIZE(new_persistent_script, sizeof(zend_persistent_script)); ADD_DUP_SIZE(key, key_length + 1); ADD_STRING(new_persistent_script->full_path); - ADD_DUP_SIZE(new_persistent_script, sizeof(zend_persistent_script)); - RETURN_SIZE(); + zend_accel_persist_class_table_calc(&new_persistent_script->class_table TSRMLS_CC); + zend_hash_persist_calc(&new_persistent_script->function_table, zend_persist_op_array_calc TSRMLS_CC); + zend_persist_op_array_calc_ex(&new_persistent_script->main_op_array TSRMLS_CC); + + new_persistent_script->size += new_persistent_script->arena_size; + + ZCG(current_persistent_script) = NULL; + + return new_persistent_script->size; } diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index 9ecb2a0eae..f3f7bd7d30 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -340,7 +340,7 @@ void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source TSRML /* we already duplicated this pointer */ return old_p; } - retval = ZCG(mem);; + retval = ZCG(mem); ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size)); memcpy(retval, source, size); if (free_source) { diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 1586695d96..4a958d92cf 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -977,7 +977,7 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_ ZVAL_COPY(return_value, &stmt->fetch.into); - if (zend_get_class_entry(Z_OBJ_P(return_value) TSRMLS_CC) == ZEND_STANDARD_CLASS_DEF_PTR) { + if (Z_OBJ_P(return_value)->ce == ZEND_STANDARD_CLASS_DEF_PTR) { how = PDO_FETCH_OBJ; } break; @@ -2635,18 +2635,9 @@ static union _zend_function *row_get_ctor(zend_object *object TSRMLS_DC) return (union _zend_function*)&ctor; } -static zend_class_entry *row_get_ce(const zend_object *object TSRMLS_DC) +static zend_string *row_get_classname(const zend_object *object TSRMLS_DC) { - return pdo_row_ce; -} - -static zend_string *row_get_classname(const zend_object *object, int parent TSRMLS_DC) -{ - if (parent) { - return NULL; - } else { - return zend_string_init("PDORow", sizeof("PDORow") - 1, 0); - } + return zend_string_init("PDORow", sizeof("PDORow") - 1, 0); } static int row_compare(zval *object1, zval *object2 TSRMLS_DC) @@ -2674,7 +2665,6 @@ zend_object_handlers pdo_row_object_handlers = { row_method_get, row_call_method, row_get_ctor, - row_get_ce, row_get_classname, row_compare, NULL, /* cast */ diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index d6c37e37fb..7291d64213 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4157,7 +4157,7 @@ ZEND_METHOD(reflection_class, isInstance) return; } GET_REFLECTION_OBJECT_PTR(ce); - RETURN_BOOL(HAS_CLASS_ENTRY(*object) && instanceof_function(Z_OBJCE_P(object), ce TSRMLS_CC)); + RETURN_BOOL(instanceof_function(Z_OBJCE_P(object), ce TSRMLS_CC)); } /* }}} */ diff --git a/ext/session/session.c b/ext/session/session.c index 63bb00e06a..dae965b048 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -2105,10 +2105,7 @@ static PHP_FUNCTION(session_unset) } IF_SESSION_VARS() { - HashTable *ht_sess_var; - - SEPARATE_ZVAL_IF_NOT_REF(&PS(http_session_vars)); - ht_sess_var = Z_ARRVAL_P(Z_REFVAL(PS(http_session_vars))); + HashTable *ht_sess_var = Z_ARRVAL_P(Z_REFVAL(PS(http_session_vars))); /* Clean $_SESSION. */ zend_hash_clean(ht_sess_var); diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 366a6f0d3b..ba70ecca9d 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -1958,7 +1958,6 @@ static zend_object_handlers sxe_object_handlers = { /* {{{ */ NULL, /* zend_get_std_object_handlers()->get_method,*/ NULL, /* zend_get_std_object_handlers()->call_method,*/ NULL, /* zend_get_std_object_handlers()->get_constructor, */ - NULL, /* zend_get_std_object_handlers()->get_class_entry,*/ NULL, /* zend_get_std_object_handlers()->get_class_name,*/ sxe_objects_compare, sxe_object_cast, @@ -2580,7 +2579,6 @@ PHP_MINIT_FUNCTION(simplexml) sxe_object_handlers.clone_obj = sxe_object_clone; sxe_object_handlers.get_method = zend_get_std_object_handlers()->get_method; sxe_object_handlers.get_constructor = zend_get_std_object_handlers()->get_constructor; - sxe_object_handlers.get_class_entry = zend_get_std_object_handlers()->get_class_entry; sxe_object_handlers.get_class_name = zend_get_std_object_handlers()->get_class_name; sxe_class_entry->serialize = zend_class_serialize_deny; sxe_class_entry->unserialize = zend_class_unserialize_deny; diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 3a091faddd..7c03b9ced4 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -93,7 +93,7 @@ static void soap_error_handler(int error_num, const char *error_filename, const int _old_soap_version = SOAP_GLOBAL(soap_version);\ zend_bool _old_in_compilation = CG(in_compilation); \ zend_execute_data *_old_current_execute_data = EG(current_execute_data); \ - zval *_old_stack_top = EG(argument_stack)->top; \ + zval *_old_stack_top = EG(vm_stack_top); \ int _bailout = 0;\ SOAP_GLOBAL(use_soap_error_handler) = 1;\ SOAP_GLOBAL(error_code) = "Client";\ @@ -105,18 +105,19 @@ static void soap_error_handler(int error_num, const char *error_filename, const CG(in_compilation) = _old_in_compilation; \ EG(current_execute_data) = _old_current_execute_data; \ if (EG(exception) == NULL || \ - !instanceof_function(zend_get_class_entry(EG(exception) TSRMLS_CC), soap_fault_class_entry TSRMLS_CC)) {\ + !instanceof_function(EG(exception)->ce, soap_fault_class_entry TSRMLS_CC)) {\ _bailout = 1;\ }\ - if (_old_stack_top != EG(argument_stack)->top) { \ - while (EG(argument_stack)->prev != NULL && \ - ((char*)_old_stack_top < (char*)EG(argument_stack) || \ - (char*) _old_stack_top > (char*)EG(argument_stack)->end)) { \ - zend_vm_stack tmp = EG(argument_stack)->prev; \ - efree(EG(argument_stack)); \ - EG(argument_stack) = tmp; \ + if (_old_stack_top != EG(vm_stack_top)) { \ + while (EG(vm_stack)->prev != NULL && \ + ((char*)_old_stack_top < (char*)EG(vm_stack) || \ + (char*) _old_stack_top > (char*)EG(vm_stack)->end)) { \ + zend_vm_stack tmp = EG(vm_stack)->prev; \ + efree(EG(vm_stack)); \ + EG(vm_stack) = tmp; \ + EG(vm_stack_end) = tmp->end; \ } \ - EG(argument_stack)->top = _old_stack_top; \ + EG(vm_stack)->top = _old_stack_top; \ } \ } zend_end_try();\ SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\ diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 211180a08d..8aab4c49bf 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1144,7 +1144,7 @@ static void spl_array_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *array, zend_long ar_flags, int just_array TSRMLS_DC) { if (Z_TYPE_P(array) == IS_ARRAY) { - SEPARATE_ZVAL_IF_NOT_REF(array); + SEPARATE_ARRAY(array); } if (Z_TYPE_P(array) == IS_OBJECT && (Z_OBJ_HT_P(array) == &spl_handler_ArrayObject || Z_OBJ_HT_P(array) == &spl_handler_ArrayIterator)) { diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index dddc8c5e73..f47093bf4c 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -883,7 +883,7 @@ static union _zend_function *spl_recursive_it_get_method(zend_object **zobject, zval *zobj; if (!object->iterators) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "The %s instance wasn't initialized properly", zend_get_class_entry(*zobject TSRMLS_CC)->name->val); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "The %s instance wasn't initialized properly", (*zobject)->ce->name->val); } zobj = &object->iterators[level].zobject; diff --git a/ext/standard/array.c b/ext/standard/array.c index c8e79957b5..7b49b2fd13 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -331,7 +331,7 @@ PHP_FUNCTION(count) } #ifdef HAVE_SPL /* if not and the object implements Countable we call its count() method */ - if (Z_OBJ_HT_P(array)->get_class_entry && instanceof_function(Z_OBJCE_P(array), spl_ce_Countable TSRMLS_CC)) { + if (instanceof_function(Z_OBJCE_P(array), spl_ce_Countable TSRMLS_CC)) { zend_call_method_with_0_params(array, NULL, NULL, "count", &retval); if (Z_TYPE(retval) != IS_UNDEF) { RETVAL_LONG(zval_get_long(&retval)); diff --git a/ext/standard/file.h b/ext/standard/file.h index e7de88f3de..78cab4f62f 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -23,6 +23,8 @@ #ifndef FILE_H #define FILE_H +#include "php_network.h" + PHP_MINIT_FUNCTION(file); PHP_MSHUTDOWN_FUNCTION(file); @@ -73,7 +75,7 @@ PHP_FUNCTION(sys_get_temp_dir); PHP_MINIT_FUNCTION(user_streams); PHPAPI int php_le_stream_context(TSRMLS_D); -PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC); +PHPAPI int php_set_sock_blocking(php_socket_t socketd, int block TSRMLS_DC); PHPAPI int php_copy_file(const char *src, const char *dest TSRMLS_DC); PHPAPI int php_copy_file_ex(const char *src, const char *dest, int src_chk TSRMLS_DC); PHPAPI int php_copy_file_ctx(const char *src, const char *dest, int src_chk, php_stream_context *ctx TSRMLS_DC); diff --git a/ext/standard/pack.c b/ext/standard/pack.c index f2bcb09723..a95c226b97 100644 --- a/ext/standard/pack.c +++ b/ext/standard/pack.c @@ -82,6 +82,13 @@ static int machine_endian_long_map[4]; static int big_endian_long_map[4]; static int little_endian_long_map[4]; +#if SIZEOF_ZEND_LONG > 4 +/* Mappings of bytes from quads (64bit) for all endian environments */ +static int machine_endian_longlong_map[8]; +static int big_endian_longlong_map[8]; +static int little_endian_longlong_map[8]; +#endif + /* {{{ php_pack */ static void php_pack(zval *val, size_t size, int *map, char *output) @@ -98,8 +105,8 @@ static void php_pack(zval *val, size_t size, int *map, char *output) } /* }}} */ -/* pack() idea stolen from Perl (implemented formats behave the same as there) - * Implemented formats are Z, A, a, h, H, c, C, s, S, i, I, l, L, n, N, f, d, x, X, @. +/* pack() idea stolen from Perl (implemented formats behave the same as there except J and P) + * Implemented formats are Z, A, a, h, H, c, C, s, S, i, I, l, L, n, N, q, Q, J, P, f, d, x, X, @. */ /* {{{ proto string pack(string format, mixed arg1 [, mixed arg2 [, mixed ...]]) Takes one or more arguments and packs them into a binary string according to the format argument */ @@ -198,6 +205,17 @@ PHP_FUNCTION(pack) break; /* Use as many args as specified */ + case 'q': + case 'Q': + case 'J': + case 'P': +#if SIZEOF_ZEND_LONG < 8 + efree(argv); + efree(formatcodes); + efree(formatargs); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "64-bit format codes are not available for 32-bit versions of PHP"); + RETURN_FALSE; +#endif case 'c': case 'C': case 's': @@ -280,6 +298,15 @@ PHP_FUNCTION(pack) INC_OUTPUTPOS(arg,4) /* 32 bit per arg */ break; +#if SIZEOF_ZEND_LONG > 4 + case 'q': + case 'Q': + case 'J': + case 'P': + INC_OUTPUTPOS(arg,8) /* 32 bit per arg */ + break; +#endif + case 'f': INC_OUTPUTPOS(arg,sizeof(float)) break; @@ -430,6 +457,27 @@ PHP_FUNCTION(pack) break; } +#if SIZEOF_ZEND_LONG > 4 + case 'q': + case 'Q': + case 'J': + case 'P': { + int *map = machine_endian_longlong_map; + + if (code == 'J') { + map = big_endian_longlong_map; + } else if (code == 'P') { + map = little_endian_longlong_map; + } + + while (arg-- > 0) { + php_pack(&argv[currentarg++], 8, map, &output[outputpos]); + outputpos += 8; + } + break; + } +#endif + case 'f': { while (arg-- > 0) { float v = (float) zval_get_double(&argv[currentarg++]); @@ -506,7 +554,7 @@ static zend_long php_unpack(char *data, size_t size, int issigned, int *map) * chars1, chars2, and ints. * Numeric pack types will return numbers, a and A will return strings, * f and d will return doubles. - * Implemented formats are Z, A, a, h, H, c, C, s, S, i, I, l, L, n, N, f, d, x, X, @. + * Implemented formats are Z, A, a, h, H, c, C, s, S, i, I, l, L, n, N, q, Q, J, P, f, d, x, X, @. */ /* {{{ proto array unpack(string format, string input) Unpack binary string into named array elements according to format argument */ @@ -622,6 +670,20 @@ PHP_FUNCTION(unpack) size = 4; break; + /* Use 8 bytes of input */ + case 'q': + case 'Q': + case 'J': + case 'P': +#if SIZEOF_ZEND_LONG > 4 + size = 8; + break; +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "64-bit format codes are not available for 32-bit versions of PHP"); + zval_dtor(return_value); + RETURN_FALSE; +#endif + /* Use sizeof(float) bytes of input */ case 'f': size = sizeof(float); @@ -845,6 +907,38 @@ PHP_FUNCTION(unpack) break; } +#if SIZEOF_ZEND_LONG > 4 + case 'q': + case 'Q': + case 'J': + case 'P': { + int issigned = 0; + int *map = machine_endian_longlong_map; + long v = 0; + + if (type == 'q' || type == 'Q') { + issigned = input[inputpos + (machine_little_endian ? 7 : 0)] & 0x80; + } else if (type == 'J') { + issigned = input[inputpos] & 0x80; + map = big_endian_longlong_map; + } else if (type == 'P') { + issigned = input[inputpos + 7] & 0x80; + map = little_endian_longlong_map; + } + + v = php_unpack(&input[inputpos], 8, issigned, map); + + if (type == 'q') { + v = (signed long int) v; + } else { + v = (unsigned long int) v; + } + + add_assoc_long(return_value, n, v); + break; + } +#endif + case 'f': { float v; @@ -948,6 +1042,33 @@ PHP_MINIT_FUNCTION(pack) little_endian_long_map[1] = 1; little_endian_long_map[2] = 2; little_endian_long_map[3] = 3; + +#if SIZEOF_ZEND_LONG > 4 + machine_endian_longlong_map[0] = 0; + machine_endian_longlong_map[1] = 1; + machine_endian_longlong_map[2] = 2; + machine_endian_longlong_map[3] = 3; + machine_endian_longlong_map[4] = 4; + machine_endian_longlong_map[5] = 5; + machine_endian_longlong_map[6] = 6; + machine_endian_longlong_map[7] = 7; + big_endian_longlong_map[0] = 7; + big_endian_longlong_map[1] = 6; + big_endian_longlong_map[2] = 5; + big_endian_longlong_map[3] = 4; + big_endian_longlong_map[4] = 3; + big_endian_longlong_map[5] = 2; + big_endian_longlong_map[6] = 1; + big_endian_longlong_map[7] = 0; + little_endian_longlong_map[0] = 0; + little_endian_longlong_map[1] = 1; + little_endian_longlong_map[2] = 2; + little_endian_longlong_map[3] = 3; + little_endian_longlong_map[4] = 4; + little_endian_longlong_map[5] = 5; + little_endian_longlong_map[6] = 6; + little_endian_longlong_map[7] = 7; +#endif } else { zval val; @@ -980,6 +1101,33 @@ PHP_MINIT_FUNCTION(pack) little_endian_long_map[1] = size - 2; little_endian_long_map[2] = size - 3; little_endian_long_map[3] = size - 4; + +#if SIZEOF_ZEND_LONG > 4 + machine_endian_longlong_map[0] = size - 8; + machine_endian_longlong_map[1] = size - 7; + machine_endian_longlong_map[2] = size - 6; + machine_endian_longlong_map[3] = size - 5; + machine_endian_longlong_map[0] = size - 4; + machine_endian_longlong_map[1] = size - 3; + machine_endian_longlong_map[2] = size - 2; + machine_endian_longlong_map[3] = size - 1; + big_endian_longlong_map[0] = size - 8; + big_endian_longlong_map[1] = size - 7; + big_endian_longlong_map[2] = size - 6; + big_endian_longlong_map[3] = size - 5; + big_endian_longlong_map[0] = size - 4; + big_endian_longlong_map[1] = size - 3; + big_endian_longlong_map[2] = size - 2; + big_endian_longlong_map[3] = size - 1; + little_endian_longlong_map[0] = size - 1; + little_endian_longlong_map[1] = size - 2; + little_endian_longlong_map[2] = size - 3; + little_endian_longlong_map[3] = size - 4; + little_endian_longlong_map[0] = size - 5; + little_endian_longlong_map[1] = size - 6; + little_endian_longlong_map[2] = size - 7; + little_endian_longlong_map[3] = size - 8; +#endif } return SUCCESS; diff --git a/ext/standard/php_incomplete_class.h b/ext/standard/php_incomplete_class.h index 6001e35bbe..177e960765 100644 --- a/ext/standard/php_incomplete_class.h +++ b/ext/standard/php_incomplete_class.h @@ -28,15 +28,14 @@ #define PHP_SET_CLASS_ATTRIBUTES(struc) \ /* OBJECTS_FIXME: Fix for new object model */ \ - if (Z_OBJ_HT_P(struc)->get_class_entry && \ - Z_OBJCE_P(struc) == BG(incomplete_class)) { \ + if (Z_OBJCE_P(struc) == BG(incomplete_class)) { \ class_name = php_lookup_class_name(struc); \ if (!class_name) { \ class_name = zend_string_init(INCOMPLETE_CLASS, sizeof(INCOMPLETE_CLASS) - 1, 0); \ } \ incomplete_class = 1; \ } else { \ - class_name = zend_get_object_classname(Z_OBJ_P(struc) TSRMLS_CC); \ + class_name = zend_string_copy(Z_OBJCE_P(struc)->name); \ } #define PHP_CLEANUP_CLASS_ATTRIBUTES() \ diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index 9e872222fd..0b655bfbdf 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -137,8 +137,8 @@ PHPAPI size_t php_strip_tags(char *rbuf, size_t len, int *state, char *allow, si PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, char *allow, size_t allow_len, zend_bool allow_tag_spaces); PHPAPI size_t php_char_to_str_ex(char *str, size_t len, char from, char *to, size_t to_len, zval *result, int case_sensitivity, size_t *replace_count); PHPAPI size_t php_char_to_str(char *str, size_t len, char from, char *to, size_t to_len, zval *result); -PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC); -PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, zend_long limit); +PHPAPI void php_implode(const zend_string *delim, zval *arr, zval *return_value TSRMLS_DC); +PHPAPI void php_explode(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit); PHPAPI size_t php_strspn(char *s1, char *s2, char *s1_end, char *s2_end); PHPAPI size_t php_strcspn(char *s1, char *s2, char *s1_end, char *s2_end); diff --git a/ext/standard/string.c b/ext/standard/string.c index 87fde1e802..1975f19b3f 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1013,41 +1013,36 @@ PHP_FUNCTION(wordwrap) /* {{{ php_explode */ -PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, zend_long limit) +PHPAPI void php_explode(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit) { - char *p1, *p2, *endp; - - endp = Z_STRVAL_P(str) + Z_STRLEN_P(str); - - p1 = Z_STRVAL_P(str); - p2 = (char*)php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp); + char *p1 = str->val; + char *endp = str->val + str->len; + char *p2 = (char *) php_memnstr(str->val, delim->val, delim->len, endp); if (p2 == NULL) { - add_next_index_stringl(return_value, p1, Z_STRLEN_P(str)); + add_next_index_str(return_value, zend_string_copy(str)); } else { do { add_next_index_stringl(return_value, p1, p2 - p1); - p1 = p2 + Z_STRLEN_P(delim); - } while ((p2 = (char*)php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL && - --limit > 1); + p1 = p2 + delim->len; + p2 = (char *) php_memnstr(p1, delim->val, delim->len, endp); + } while (p2 != NULL && --limit > 1); - if (p1 <= endp) - add_next_index_stringl(return_value, p1, endp-p1); + if (p1 <= endp) { + add_next_index_stringl(return_value, p1, endp - p1); + } } } /* }}} */ /* {{{ php_explode_negative_limit */ -PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_value, zend_long limit) +PHPAPI void php_explode_negative_limit(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit) { #define EXPLODE_ALLOC_STEP 64 - char *p1, *p2, *endp; - - endp = Z_STRVAL_P(str) + Z_STRLEN_P(str); - - p1 = Z_STRVAL_P(str); - p2 = (char*)php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp); + char *p1 = str->val; + char *endp = str->val + str->len; + char *p2 = (char *) php_memnstr(str->val, delim->val, delim->len, endp); if (p2 == NULL) { /* @@ -1065,14 +1060,15 @@ PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_valu allocated = found + EXPLODE_ALLOC_STEP;/* make sure we have enough memory */ positions = erealloc(positions, allocated*sizeof(char *)); } - positions[found++] = p1 = p2 + Z_STRLEN_P(delim); - } while ((p2 = (char*)php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL); + positions[found++] = p1 = p2 + delim->len; + p2 = (char *) php_memnstr(p1, delim->val, delim->len, endp); + } while (p2 != NULL); to_return = limit + found; /* limit is at least -1 therefore no need of bounds checking : i will be always less than found */ - for (i = 0;i < to_return;i++) { /* this checks also for to_return > 0 */ + for (i = 0; i < to_return; i++) { /* this checks also for to_return > 0 */ add_next_index_stringl(return_value, positions[i], - (positions[i+1] - Z_STRLEN_P(delim)) - positions[i]); + (positions[i+1] - delim->len) - positions[i]); } efree(positions); } @@ -1086,7 +1082,6 @@ PHP_FUNCTION(explode) { zend_string *str, *delim; zend_long limit = ZEND_LONG_MAX; /* No limit */ - zval zdelim, zstr; #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "SS|l", &delim, &str, &limit) == FAILURE) { @@ -1110,17 +1105,15 @@ PHP_FUNCTION(explode) if (str->len == 0) { if (limit >= 0) { - add_next_index_stringl(return_value, "", sizeof("") - 1); + add_next_index_str(return_value, STR_EMPTY_ALLOC()); } return; } - ZVAL_STR(&zstr, str); - ZVAL_STR(&zdelim, delim); if (limit > 1) { - php_explode(&zdelim, &zstr, return_value, limit); + php_explode(delim, str, return_value, limit); } else if (limit < 0) { - php_explode_negative_limit(&zdelim, &zstr, return_value, limit); + php_explode_negative_limit(delim, str, return_value, limit); } else { add_index_stringl(return_value, 0, str->val, str->len); } @@ -1133,7 +1126,7 @@ PHP_FUNCTION(explode) /* {{{ php_implode */ -PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC) +PHPAPI void php_implode(const zend_string *delim, zval *arr, zval *return_value TSRMLS_DC) { zval *tmp; smart_str implstr = {0}; @@ -1170,8 +1163,8 @@ again: size_t str_len = spprintf(&stmp, 0, "%.*G", (int) EG(precision), Z_DVAL_P(tmp)); smart_str_appendl(&implstr, stmp, str_len); efree(stmp); - } break; + } case IS_REFERENCE: tmp = Z_REFVAL_P(tmp); @@ -1186,7 +1179,7 @@ again: } if (++i != numelems) { - smart_str_append(&implstr, Z_STR_P(delim)); + smart_str_append(&implstr, delim); } } ZEND_HASH_FOREACH_END(); @@ -1205,7 +1198,8 @@ again: Joins array elements placing glue string between items and return one string */ PHP_FUNCTION(implode) { - zval *arg1 = NULL, *arg2 = NULL, *delim, *arr, tmp; + zval *arg1, *arg2 = NULL, *arr; + zend_string *delim; #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &arg1, &arg2) == FAILURE) { @@ -1225,20 +1219,15 @@ PHP_FUNCTION(implode) return; } - ZVAL_EMPTY_STRING(&tmp); - delim = &tmp; - - SEPARATE_ZVAL(arg1); + delim = STR_EMPTY_ALLOC(); arr = arg1; } else { if (Z_TYPE_P(arg1) == IS_ARRAY) { + delim = zval_get_string(arg2); arr = arg1; - convert_to_string_ex(arg2); - delim = arg2; } else if (Z_TYPE_P(arg2) == IS_ARRAY) { + delim = zval_get_string(arg1); arr = arg2; - convert_to_string_ex(arg1); - delim = arg1; } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid arguments passed"); return; @@ -1246,6 +1235,7 @@ PHP_FUNCTION(implode) } php_implode(delim, arr, return_value TSRMLS_CC); + zend_string_release(delim); } /* }}} */ diff --git a/ext/standard/tests/strings/pack64.phpt b/ext/standard/tests/strings/pack64.phpt new file mode 100644 index 0000000000..9bc24928fe --- /dev/null +++ b/ext/standard/tests/strings/pack64.phpt @@ -0,0 +1,115 @@ +--TEST-- +64bit pack()/unpack() tests +--SKIPIF-- +<?php +if (PHP_INT_SIZE < 8) { + die("skip 64bit test only"); +} +?> +--FILE-- +<?php +print_r(unpack("Q", pack("Q", 0xfffffffffffe))); +print_r(unpack("Q", pack("Q", 0))); +print_r(unpack("Q", pack("Q", 0x8000000000000002))); +print_r(unpack("Q", pack("Q", -1))); +print_r(unpack("Q", pack("Q", 0x8000000000000000))); + +print_r(unpack("J", pack("J", 0xfffffffffffe))); +print_r(unpack("J", pack("J", 0))); +print_r(unpack("J", pack("J", 0x8000000000000002))); +print_r(unpack("J", pack("J", -1))); +print_r(unpack("J", pack("J", 0x8000000000000000))); + +print_r(unpack("P", pack("P", 0xfffffffffffe))); +print_r(unpack("P", pack("P", 0))); +print_r(unpack("P", pack("P", 0x8000000000000002))); +print_r(unpack("P", pack("P", -1))); +print_r(unpack("P", pack("P", 0x8000000000000000))); + +print_r(unpack("q", pack("q", 0xfffffffffffe))); +print_r(unpack("q", pack("q", 0))); +print_r(unpack("q", pack("q", 0x8000000000000002))); +print_r(unpack("q", pack("q", -1))); +print_r(unpack("q", pack("q", 0x8000000000000000))); +?> +--EXPECTF-- +Array +( + [1] => 281474976710654 +) +Array +( + [1] => 0 +) +Array +( + [1] => -9223372036854775808 +) +Array +( + [1] => -1 +) +Array +( + [1] => -9223372036854775808 +) +Array +( + [1] => 281474976710654 +) +Array +( + [1] => 0 +) +Array +( + [1] => -9223372036854775808 +) +Array +( + [1] => -1 +) +Array +( + [1] => -9223372036854775808 +) +Array +( + [1] => 281474976710654 +) +Array +( + [1] => 0 +) +Array +( + [1] => -9223372036854775808 +) +Array +( + [1] => -1 +) +Array +( + [1] => -9223372036854775808 +) +Array +( + [1] => 281474976710654 +) +Array +( + [1] => 0 +) +Array +( + [1] => -9223372036854775808 +) +Array +( + [1] => -1 +) +Array +( + [1] => -9223372036854775808 +) diff --git a/ext/standard/tests/strings/pack64_32.phpt b/ext/standard/tests/strings/pack64_32.phpt new file mode 100644 index 0000000000..f52de63ca4 --- /dev/null +++ b/ext/standard/tests/strings/pack64_32.phpt @@ -0,0 +1,44 @@ +--TEST-- +64bit pack()/unpack() tests +--SKIPIF-- +<?php +if (PHP_INT_SIZE > 4) { + die("skip 32bit test only"); +} +?> +--FILE-- +<?php +var_dump(pack("Q", 0)); +var_dump(pack("J", 0)); +var_dump(pack("P", 0)); +var_dump(pack("q", 0)); + +var_dump(unpack("Q", '')); +var_dump(unpack("J", '')); +var_dump(unpack("P", '')); +var_dump(unpack("q", '')); +?> +--EXPECTF-- +Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d +bool(false) + +Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d +bool(false) + +Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d +bool(false) + +Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d +bool(false) + +Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d +bool(false) + +Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d +bool(false) + +Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d +bool(false) + +Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d +bool(false) diff --git a/ext/standard/tests/strings/url_t.phpt b/ext/standard/tests/strings/url_t.phpt index e0e5411036..e172061ec2 100644 --- a/ext/standard/tests/strings/url_t.phpt +++ b/ext/standard/tests/strings/url_t.phpt @@ -75,6 +75,7 @@ $sample_urls = array ( ); foreach ($sample_urls as $url) { + echo "\n--> $url: "; var_dump(@parse_url($url)); } @@ -84,21 +85,24 @@ $sample_urls = array ( } ?> --EXPECT-- -array(1) { +--> : array(1) { ["path"]=> string(0) "" } -array(1) { + +--> 64.246.30.37: array(1) { ["path"]=> string(12) "64.246.30.37" } -array(2) { + +--> http://64.246.30.37: array(2) { ["scheme"]=> string(4) "http" ["host"]=> string(12) "64.246.30.37" } -array(3) { + +--> http://64.246.30.37/: array(3) { ["scheme"]=> string(4) "http" ["host"]=> @@ -106,11 +110,13 @@ array(3) { ["path"]=> string(1) "/" } -array(1) { + +--> 64.246.30.37/: array(1) { ["path"]=> string(13) "64.246.30.37/" } -array(3) { + +--> 64.246.30.37:80/: array(3) { ["host"]=> string(12) "64.246.30.37" ["port"]=> @@ -118,21 +124,25 @@ array(3) { ["path"]=> string(1) "/" } -array(1) { + +--> php.net: array(1) { ["path"]=> string(7) "php.net" } -array(1) { + +--> php.net/: array(1) { ["path"]=> string(8) "php.net/" } -array(2) { + +--> http://php.net: array(2) { ["scheme"]=> string(4) "http" ["host"]=> string(7) "php.net" } -array(3) { + +--> http://php.net/: array(3) { ["scheme"]=> string(4) "http" ["host"]=> @@ -140,21 +150,25 @@ array(3) { ["path"]=> string(1) "/" } -array(1) { + +--> www.php.net: array(1) { ["path"]=> string(11) "www.php.net" } -array(1) { + +--> www.php.net/: array(1) { ["path"]=> string(12) "www.php.net/" } -array(2) { + +--> http://www.php.net: array(2) { ["scheme"]=> string(4) "http" ["host"]=> string(11) "www.php.net" } -array(3) { + +--> http://www.php.net/: array(3) { ["scheme"]=> string(4) "http" ["host"]=> @@ -162,13 +176,15 @@ array(3) { ["path"]=> string(1) "/" } -array(2) { + +--> www.php.net:80: array(2) { ["host"]=> string(11) "www.php.net" ["port"]=> int(80) } -array(3) { + +--> http://www.php.net:80: array(3) { ["scheme"]=> string(4) "http" ["host"]=> @@ -176,7 +192,8 @@ array(3) { ["port"]=> int(80) } -array(4) { + +--> http://www.php.net:80/: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -186,7 +203,8 @@ array(4) { ["path"]=> string(1) "/" } -array(3) { + +--> http://www.php.net/index.php: array(3) { ["scheme"]=> string(4) "http" ["host"]=> @@ -194,11 +212,13 @@ array(3) { ["path"]=> string(10) "/index.php" } -array(1) { + +--> www.php.net/?: array(1) { ["path"]=> string(12) "www.php.net/" } -array(3) { + +--> www.php.net:80/?: array(3) { ["host"]=> string(11) "www.php.net" ["port"]=> @@ -206,7 +226,8 @@ array(3) { ["path"]=> string(1) "/" } -array(3) { + +--> http://www.php.net/?: array(3) { ["scheme"]=> string(4) "http" ["host"]=> @@ -214,7 +235,8 @@ array(3) { ["path"]=> string(1) "/" } -array(4) { + +--> http://www.php.net:80/?: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -224,7 +246,8 @@ array(4) { ["path"]=> string(1) "/" } -array(4) { + +--> http://www.php.net:80/index.php: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -234,7 +257,8 @@ array(4) { ["path"]=> string(10) "/index.php" } -array(4) { + +--> http://www.php.net:80/foo/bar/index.php: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -244,7 +268,8 @@ array(4) { ["path"]=> string(18) "/foo/bar/index.php" } -array(4) { + +--> http://www.php.net:80/this/is/a/very/deep/directory/structure/and/file.php: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -254,7 +279,8 @@ array(4) { ["path"]=> string(53) "/this/is/a/very/deep/directory/structure/and/file.php" } -array(5) { + +--> http://www.php.net:80/this/is/a/very/deep/directory/structure/and/file.php?lots=1&of=2¶meters=3&too=4&here=5: array(5) { ["scheme"]=> string(4) "http" ["host"]=> @@ -266,7 +292,8 @@ array(5) { ["query"]=> string(37) "lots=1&of=2¶meters=3&too=4&here=5" } -array(4) { + +--> http://www.php.net:80/this/is/a/very/deep/directory/structure/and/: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -276,7 +303,8 @@ array(4) { ["path"]=> string(45) "/this/is/a/very/deep/directory/structure/and/" } -array(4) { + +--> http://www.php.net:80/this/is/a/very/deep/directory/structure/and/file.php: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -286,7 +314,8 @@ array(4) { ["path"]=> string(53) "/this/is/a/very/deep/directory/structure/and/file.php" } -array(4) { + +--> http://www.php.net:80/this/../a/../deep/directory: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -296,7 +325,8 @@ array(4) { ["path"]=> string(28) "/this/../a/../deep/directory" } -array(4) { + +--> http://www.php.net:80/this/../a/../deep/directory/: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -306,7 +336,8 @@ array(4) { ["path"]=> string(29) "/this/../a/../deep/directory/" } -array(4) { + +--> http://www.php.net:80/this/is/a/very/deep/directory/../file.php: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -316,7 +347,8 @@ array(4) { ["path"]=> string(42) "/this/is/a/very/deep/directory/../file.php" } -array(4) { + +--> http://www.php.net:80/index.php: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -326,7 +358,8 @@ array(4) { ["path"]=> string(10) "/index.php" } -array(4) { + +--> http://www.php.net:80/index.php?: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -336,7 +369,8 @@ array(4) { ["path"]=> string(10) "/index.php" } -array(5) { + +--> http://www.php.net:80/#foo: array(5) { ["scheme"]=> string(4) "http" ["host"]=> @@ -348,7 +382,8 @@ array(5) { ["fragment"]=> string(3) "foo" } -array(4) { + +--> http://www.php.net:80/?#: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -358,7 +393,8 @@ array(4) { ["path"]=> string(1) "/" } -array(5) { + +--> http://www.php.net:80/?test=1: array(5) { ["scheme"]=> string(4) "http" ["host"]=> @@ -370,7 +406,8 @@ array(5) { ["query"]=> string(6) "test=1" } -array(4) { + +--> http://www.php.net/?test=1&: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -380,7 +417,8 @@ array(4) { ["query"]=> string(7) "test=1&" } -array(5) { + +--> http://www.php.net:80/?&: array(5) { ["scheme"]=> string(4) "http" ["host"]=> @@ -392,7 +430,8 @@ array(5) { ["query"]=> string(1) "&" } -array(5) { + +--> http://www.php.net:80/index.php?test=1&: array(5) { ["scheme"]=> string(4) "http" ["host"]=> @@ -404,7 +443,8 @@ array(5) { ["query"]=> string(7) "test=1&" } -array(4) { + +--> http://www.php.net/index.php?&: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -414,7 +454,8 @@ array(4) { ["query"]=> string(1) "&" } -array(5) { + +--> http://www.php.net:80/index.php?foo&: array(5) { ["scheme"]=> string(4) "http" ["host"]=> @@ -426,7 +467,8 @@ array(5) { ["query"]=> string(4) "foo&" } -array(4) { + +--> http://www.php.net/index.php?&foo: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -436,7 +478,8 @@ array(4) { ["query"]=> string(4) "&foo" } -array(5) { + +--> http://www.php.net:80/index.php?test=1&test2=char&test3=mixesCI: array(5) { ["scheme"]=> string(4) "http" ["host"]=> @@ -448,7 +491,8 @@ array(5) { ["query"]=> string(31) "test=1&test2=char&test3=mixesCI" } -array(5) { + +--> www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(5) { ["host"]=> string(11) "www.php.net" ["port"]=> @@ -460,7 +504,8 @@ array(5) { ["fragment"]=> string(16) "some_page_ref123" } -array(7) { + +--> http://secret@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) { ["scheme"]=> string(4) "http" ["host"]=> @@ -476,13 +521,16 @@ array(7) { ["fragment"]=> string(16) "some_page_ref123" } -array(6) { + +--> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) { ["scheme"]=> string(4) "http" ["host"]=> string(11) "www.php.net" ["user"]=> string(6) "secret" + ["pass"]=> + string(0) "" ["path"]=> string(10) "/index.php" ["query"]=> @@ -490,13 +538,16 @@ array(6) { ["fragment"]=> string(16) "some_page_ref123" } -array(7) { + +--> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(8) { ["scheme"]=> string(4) "http" ["host"]=> string(11) "www.php.net" ["port"]=> int(80) + ["user"]=> + string(0) "" ["pass"]=> string(7) "hideout" ["path"]=> @@ -506,7 +557,8 @@ array(7) { ["fragment"]=> string(16) "some_page_ref123" } -array(7) { + +--> http://secret:hideout@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) { ["scheme"]=> string(4) "http" ["host"]=> @@ -522,7 +574,8 @@ array(7) { ["fragment"]=> string(16) "some_page_ref123" } -array(7) { + +--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) { ["scheme"]=> string(4) "http" ["host"]=> @@ -538,7 +591,8 @@ array(7) { ["fragment"]=> string(16) "some_page_ref123" } -array(8) { + +--> http://secret:hid:out@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(8) { ["scheme"]=> string(4) "http" ["host"]=> @@ -556,13 +610,15 @@ array(8) { ["fragment"]=> string(16) "some_page_ref123" } -array(2) { + +--> nntp://news.php.net: array(2) { ["scheme"]=> string(4) "nntp" ["host"]=> string(12) "news.php.net" } -array(3) { + +--> ftp://ftp.gnu.org/gnu/glic/glibc.tar.gz: array(3) { ["scheme"]=> string(3) "ftp" ["host"]=> @@ -570,25 +626,29 @@ array(3) { ["path"]=> string(22) "/gnu/glic/glibc.tar.gz" } -array(2) { + +--> zlib:http://foo@bar: array(2) { ["scheme"]=> string(4) "zlib" ["path"]=> string(14) "http://foo@bar" } -array(2) { + +--> zlib:filename.txt: array(2) { ["scheme"]=> string(4) "zlib" ["path"]=> string(12) "filename.txt" } -array(2) { + +--> zlib:/path/to/my/file/file.txt: array(2) { ["scheme"]=> string(4) "zlib" ["path"]=> string(25) "/path/to/my/file/file.txt" } -array(3) { + +--> foo://foo@bar: array(3) { ["scheme"]=> string(3) "foo" ["host"]=> @@ -596,25 +656,29 @@ array(3) { ["user"]=> string(3) "foo" } -array(2) { + +--> mailto:me@mydomain.com: array(2) { ["scheme"]=> string(6) "mailto" ["path"]=> string(15) "me@mydomain.com" } -array(2) { + +--> /foo.php?a=b&c=d: array(2) { ["path"]=> string(8) "/foo.php" ["query"]=> string(7) "a=b&c=d" } -array(2) { + +--> foo.php?a=b&c=d: array(2) { ["path"]=> string(7) "foo.php" ["query"]=> string(7) "a=b&c=d" } -array(6) { + +--> http://user:passwd@www.example.com:8080?bar=1&boom=0: array(6) { ["scheme"]=> string(4) "http" ["host"]=> @@ -628,13 +692,15 @@ array(6) { ["query"]=> string(12) "bar=1&boom=0" } -array(2) { + +--> file:///path/to/file: array(2) { ["scheme"]=> string(4) "file" ["path"]=> string(13) "/path/to/file" } -array(3) { + +--> file://path/to/file: array(3) { ["scheme"]=> string(4) "file" ["host"]=> @@ -642,13 +708,15 @@ array(3) { ["path"]=> string(8) "/to/file" } -array(2) { + +--> file:/path/to/file: array(2) { ["scheme"]=> string(4) "file" ["path"]=> string(13) "/path/to/file" } -array(4) { + +--> http://1.2.3.4:/abc.asp?a=1&b=2: array(4) { ["scheme"]=> string(4) "http" ["host"]=> @@ -658,7 +726,8 @@ array(4) { ["query"]=> string(7) "a=1&b=2" } -array(3) { + +--> http://foo.com#bar: array(3) { ["scheme"]=> string(4) "http" ["host"]=> @@ -666,11 +735,13 @@ array(3) { ["fragment"]=> string(3) "bar" } -array(1) { + +--> scheme:: array(1) { ["scheme"]=> string(6) "scheme" } -array(4) { + +--> foo+bar://baz@bang/bla: array(4) { ["scheme"]=> string(7) "foo+bar" ["host"]=> @@ -680,13 +751,15 @@ array(4) { ["path"]=> string(4) "/bla" } -array(2) { + +--> gg:9130731: array(2) { ["scheme"]=> string(2) "gg" ["path"]=> string(7) "9130731" } -array(7) { + +--> http://user:@pass@host/path?argument?value#etc: array(7) { ["scheme"]=> string(4) "http" ["host"]=> @@ -710,3 +783,4 @@ string(7) "hideout" string(10) "/index.php" string(31) "test=1&test2=char&test3=mixesCI" string(16) "some_page_ref123" + diff --git a/ext/standard/tests/url/parse_url_basic_001.phpt b/ext/standard/tests/url/parse_url_basic_001.phpt index a6f4f7a252..0708691fe3 100644 --- a/ext/standard/tests/url/parse_url_basic_001.phpt +++ b/ext/standard/tests/url/parse_url_basic_001.phpt @@ -454,13 +454,15 @@ echo "Done"; string(16) "some_page_ref123" } ---> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(6) { +--> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) { ["scheme"]=> string(4) "http" ["host"]=> string(11) "www.php.net" ["user"]=> string(6) "secret" + ["pass"]=> + string(0) "" ["path"]=> string(10) "/index.php" ["query"]=> @@ -469,13 +471,15 @@ echo "Done"; string(16) "some_page_ref123" } ---> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) { +--> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(8) { ["scheme"]=> string(4) "http" ["host"]=> string(11) "www.php.net" ["port"]=> int(80) + ["user"]=> + string(0) "" ["pass"]=> string(7) "hideout" ["path"]=> diff --git a/ext/standard/tests/url/parse_url_basic_005.phpt b/ext/standard/tests/url/parse_url_basic_005.phpt index 1fc946e5b3..5b2cb98f8b 100644 --- a/ext/standard/tests/url/parse_url_basic_005.phpt +++ b/ext/standard/tests/url/parse_url_basic_005.phpt @@ -66,7 +66,7 @@ echo "Done"; --> www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : NULL --> http://secret@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret" --> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret" ---> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : NULL +--> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(0) "" --> http://secret:hideout@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret" --> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(14) "secret@hideout" --> http://secret:hid:out@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret" diff --git a/ext/standard/tests/url/parse_url_basic_006.phpt b/ext/standard/tests/url/parse_url_basic_006.phpt index 5104326198..79af6b8b62 100644 --- a/ext/standard/tests/url/parse_url_basic_006.phpt +++ b/ext/standard/tests/url/parse_url_basic_006.phpt @@ -65,7 +65,7 @@ echo "Done"; --> http://www.php.net:80/index.php?test=1&test2=char&test3=mixesCI : NULL --> www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : NULL --> http://secret@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : NULL ---> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : NULL +--> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(0) "" --> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(7) "hideout" --> http://secret:hideout@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(7) "hideout" --> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : NULL diff --git a/ext/standard/type.c b/ext/standard/type.c index fa5cd4639e..67d5ed1e75 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -219,12 +219,7 @@ static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type) if (Z_TYPE_P(arg) == type) { if (type == IS_OBJECT) { - zend_class_entry *ce; - if (Z_OBJ_HT_P(arg)->get_class_entry == NULL) { - /* if there's no get_class_entry it's not a PHP object, so it can't be INCOMPLETE_CLASS */ - RETURN_TRUE; - } - ce = Z_OBJCE_P(arg); + zend_class_entry *ce = Z_OBJCE_P(arg); if (ce->name->len == sizeof(INCOMPLETE_CLASS) - 1 && !strncmp(ce->name->val, INCOMPLETE_CLASS, ce->name->len)) { RETURN_FALSE; diff --git a/ext/standard/url.c b/ext/standard/url.c index 81f9b2ac9a..4fb2c73edb 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -240,16 +240,12 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) /* check for login and password */ if ((p = zend_memrchr(s, '@', (e-s)))) { if ((pp = memchr(s, ':', (p-s)))) { - if ((pp-s) > 0) { - ret->user = estrndup(s, (pp-s)); - php_replace_controlchars_ex(ret->user, (pp - s)); - } + ret->user = estrndup(s, (pp-s)); + php_replace_controlchars_ex(ret->user, (pp - s)); pp++; - if (p-pp > 0) { - ret->pass = estrndup(pp, (p-pp)); - php_replace_controlchars_ex(ret->pass, (p-pp)); - } + ret->pass = estrndup(pp, (p-pp)); + php_replace_controlchars_ex(ret->pass, (p-pp)); } else { ret->user = estrndup(s, (p-s)); php_replace_controlchars_ex(ret->user, (p-s)); diff --git a/ext/standard/var.c b/ext/standard/var.c index 53fd54c647..6e5bd703d3 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -163,13 +163,10 @@ again: return; } - if (Z_OBJ_HANDLER_P(struc, get_class_name)) { - class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc), 0 TSRMLS_CC); - php_printf("%sobject(%s)#%d (%d) {\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0); - zend_string_release(class_name); - } else { - php_printf("%sobject(unknown class)#%d (%d) {\n", COMMON, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0); - } + class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc) TSRMLS_CC); + php_printf("%sobject(%s)#%d (%d) {\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0); + zend_string_release(class_name); + if (myht) { zend_ulong num; zend_string *key; @@ -334,7 +331,7 @@ again: myht->u.v.nApplyCount++; } } - class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc), 0 TSRMLS_CC); + class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc) TSRMLS_CC); php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0, Z_REFCOUNT_P(struc)); zend_string_release(class_name); if (myht) { @@ -456,7 +453,6 @@ PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf TSRMLS_DC) HashTable *myht; char *tmp_str; size_t tmp_len; - zend_string *class_name; zend_string *ztmp, *ztmp2; zend_ulong index; zend_string *key; @@ -533,12 +529,10 @@ again: smart_str_appendc(buf, '\n'); buffer_append_spaces(buf, level - 1); } - class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc), 0 TSRMLS_CC); - smart_str_append(buf, class_name); + smart_str_append(buf, Z_OBJCE_P(struc)->name); smart_str_appendl(buf, "::__set_state(array(\n", 21); - zend_string_release(class_name); if (myht) { ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) { php_object_element_export(val, index, key, level, buf TSRMLS_CC); @@ -727,8 +721,7 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt php_var_serialize_string(buf, Z_STRVAL_P(name), Z_STRLEN_P(name)); php_var_serialize_intern(buf, d, var_hash TSRMLS_CC); } else { - zend_class_entry *ce; - ce = zend_get_class_entry(Z_OBJ_P(struc) TSRMLS_CC); + zend_class_entry *ce = Z_OBJ_P(struc)->ce; if (ce) { zend_string *prot_name, *priv_name; @@ -838,13 +831,9 @@ again: zval retval; zval fname; int res; - zend_class_entry *ce = NULL; - - if (Z_OBJ_HT_P(struc)->get_class_entry) { - ce = Z_OBJCE_P(struc); - } + zend_class_entry *ce = Z_OBJCE_P(struc); - if (ce && ce->serialize != NULL) { + if (ce->serialize != NULL) { /* has custom handler */ unsigned char *serialized_data = NULL; size_t serialized_length; diff --git a/main/network.c b/main/network.c index 34a4d04c81..073f1b740a 100644 --- a/main/network.c +++ b/main/network.c @@ -1123,7 +1123,7 @@ PHPAPI php_stream *_php_stream_sock_open_host(const char *host, unsigned short p return stream; } -PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC) +PHPAPI int php_set_sock_blocking(php_socket_t socketd, int block TSRMLS_DC) { int ret = SUCCESS; int flags; diff --git a/sapi/cli/php_http_parser.c b/sapi/cli/php_http_parser.c index d3bc496f4e..cc649af79a 100644 --- a/sapi/cli/php_http_parser.c +++ b/sapi/cli/php_http_parser.c @@ -1431,7 +1431,9 @@ size_t php_http_parser_execute (php_http_parser *parser, } case s_body_identity: - to_read = MIN(pe - p, (size_t)parser->content_length); + assert(pe >= p); + + to_read = MIN((size_t)(pe - p), (size_t)parser->content_length); if (to_read > 0) { if (settings->on_body) settings->on_body(parser, p, to_read); p += to_read - 1; @@ -1515,8 +1517,9 @@ size_t php_http_parser_execute (php_http_parser *parser, case s_chunk_data: { assert(parser->flags & F_CHUNKED); + assert(pe >= p); - to_read = MIN(pe - p, (size_t)(parser->content_length)); + to_read = MIN((size_t)(pe - p), (size_t)(parser->content_length)); if (to_read > 0) { if (settings->on_body) settings->on_body(parser, p, to_read); diff --git a/sapi/cli/ps_title.c b/sapi/cli/ps_title.c index 0be94e3eb0..97eec86e5b 100644 --- a/sapi/cli/ps_title.c +++ b/sapi/cli/ps_title.c @@ -386,7 +386,7 @@ int get_ps_title(int *displen, const char** string) return rc; #ifdef PS_USE_WIN32 - if (!(ps_buffer_cur_len = GetConsoleTitle(ps_buffer, ps_buffer_size))) + if (!(ps_buffer_cur_len = GetConsoleTitle(ps_buffer, (DWORD)ps_buffer_size))) return PS_TITLE_WINDOWS_ERROR; #endif *displen = (int)ps_buffer_cur_len; |