diff options
Diffstat (limited to 'Zend/zend_vm_execute.h')
-rw-r--r-- | Zend/zend_vm_execute.h | 2169 |
1 files changed, 1629 insertions, 540 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b967d281dc..72c7fe4529 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1296,9 +1296,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -1333,22 +1334,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV if (!0) { zval_ptr_dtor(ret); } - - } else { /* ZEND_OVERLOADED_FUNCTION */ - zval retval; - - ret = 0 ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (!0) { - zval_ptr_dtor(ret); - } } fcall_end: @@ -1406,9 +1391,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -1443,22 +1429,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV if (!1) { zval_ptr_dtor(ret); } - - } else { /* ZEND_OVERLOADED_FUNCTION */ - zval retval; - - ret = 1 ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (!1) { - zval_ptr_dtor(ret); - } } fcall_end: @@ -1735,16 +1705,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O goto send_array; } } - zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); + zend_type_error("call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func)); } else if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_RELEASE_THIS) { OBJ_RELEASE(Z_OBJ(EX(call)->This)); } - EX(call)->func = (zend_function*)&zend_pass_function; - Z_OBJ(EX(call)->This) = NULL; - ZEND_CALL_INFO(EX(call)) &= ~(ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS); FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var); + FREE_OP(free_op1); + HANDLE_EXCEPTION(); } else { uint32_t arg_num; HashTable *ht; @@ -2044,9 +2013,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEN ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (EG(error_reporting)) { + if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) { do { - EG(error_reporting) = 0; + /* Do not silence fatal errors */ + EG(error_reporting) &= E_FATAL_ERRORS; if (!EG(error_reporting_ini_entry)) { zval *zv = zend_hash_find_ex(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), 1); if (zv) { @@ -2581,7 +2551,7 @@ try_function_name: if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -2750,7 +2720,7 @@ try_function_name: if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -2868,7 +2838,7 @@ try_function_name: if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -3534,6 +3504,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ USE_OPLINE zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -3567,9 +3538,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -3590,7 +3562,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -3773,20 +3745,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_CONST != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { @@ -4184,8 +4163,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST } zval_ptr_dtor(&tmp); } - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } @@ -5186,9 +5165,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -5207,17 +5188,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -5225,11 +5206,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -5280,9 +5268,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -5301,17 +5291,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -5319,9 +5309,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -5571,7 +5567,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -5698,7 +5693,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -5729,13 +5723,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -5772,16 +5762,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS SAVE_OPLINE(); function_name = RT_CONSTANT(opline, opline->op2); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -5813,14 +5795,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -6104,6 +6082,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); @@ -6128,9 +6107,19 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -7384,9 +7373,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -7405,17 +7396,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -7423,11 +7414,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -7478,9 +7476,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -7499,17 +7499,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -7517,9 +7517,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -7769,7 +7775,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -7896,7 +7901,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -7927,13 +7931,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -7970,16 +7970,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV SAVE_OPLINE(); function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -8012,14 +8004,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -8232,6 +8220,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); @@ -8256,9 +8245,19 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: zval_ptr_dtor_nogc(free_op2); @@ -8888,7 +8887,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -8919,13 +8917,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -9444,18 +9438,20 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_ count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -10119,9 +10115,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -10140,17 +10138,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -10158,11 +10156,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -10213,9 +10218,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -10234,17 +10241,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -10252,9 +10259,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -10504,7 +10517,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -10631,7 +10643,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -10662,13 +10673,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -10705,16 +10712,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H SAVE_OPLINE(); function_name = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -10746,14 +10745,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -10966,6 +10961,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); @@ -10990,9 +10986,19 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -12749,6 +12755,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND USE_OPLINE zend_free_op free_op1; zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -12782,9 +12789,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); zval_ptr_dtor_nogc(free_op1); @@ -12805,7 +12813,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); zval_ptr_dtor_nogc(free_op1); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -12959,8 +12967,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN } zval_ptr_dtor(&tmp); } - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } zval_ptr_dtor_nogc(free_op1); @@ -13801,9 +13809,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -13822,17 +13832,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -13840,11 +13850,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -13895,9 +13912,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -13916,17 +13935,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -13934,9 +13953,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -14160,7 +14185,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -14366,6 +14390,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -14390,9 +14415,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -15385,9 +15420,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -15406,17 +15443,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -15424,11 +15461,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -15479,9 +15523,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -15500,17 +15546,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -15518,9 +15564,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -15744,7 +15796,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -15950,6 +16001,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -15974,9 +16026,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: zval_ptr_dtor_nogc(free_op2); @@ -16836,9 +16898,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -16857,17 +16921,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -16875,11 +16939,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -16930,9 +17001,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -16951,17 +17024,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -16969,9 +17042,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -17195,7 +17274,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -17401,6 +17479,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -17425,9 +17504,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -17870,20 +17959,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_TMP_VAR != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { @@ -18004,7 +18100,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(Z { USE_OPLINE - if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } ZEND_VM_NEXT_OPCODE(); @@ -19812,18 +19909,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMP_UNUSED_HANDLER( count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -21225,20 +21324,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE zval_ptr_dtor_nogc(free_op1); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_VAR != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); zval_ptr_dtor_nogc(free_op1); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -21972,6 +22078,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -21998,8 +22106,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -22036,7 +22150,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -22569,6 +22686,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -22593,8 +22712,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -22608,7 +22733,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -22635,6 +22763,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -22659,8 +22789,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -22673,7 +22809,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -22870,6 +23009,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D USE_OPLINE zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -22894,8 +23035,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -22985,7 +23127,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -23004,6 +23156,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D USE_OPLINE zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -23028,8 +23182,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -23119,7 +23274,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -23138,6 +23303,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D USE_OPLINE zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -23162,8 +23329,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -23253,7 +23421,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -23272,6 +23450,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D USE_OPLINE zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -23296,8 +23476,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -23387,7 +23568,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -24168,7 +24359,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -24199,13 +24389,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -24493,7 +24679,7 @@ num_index_dim: if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -24509,6 +24695,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL zend_free_op free_op1; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -24528,7 +24715,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -24723,6 +24918,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -24749,8 +24946,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -24787,7 +24990,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -25322,6 +25528,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -25346,8 +25554,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -25361,7 +25575,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -25389,6 +25606,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -25413,8 +25632,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -25427,7 +25652,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -25626,6 +25854,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ USE_OPLINE zend_free_op free_op1, free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -25650,8 +25880,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -25741,7 +25972,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -25760,6 +26001,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ USE_OPLINE zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -25784,8 +26027,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -25875,7 +26119,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -25894,6 +26148,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ USE_OPLINE zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -25918,8 +26174,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -26009,7 +26266,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -26028,6 +26295,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ USE_OPLINE zend_free_op free_op1, free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -26052,8 +26321,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -26143,7 +26413,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -26868,7 +27148,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -26899,13 +27178,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -27122,7 +27397,7 @@ num_index_dim: if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -27139,6 +27414,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND zend_free_op free_op1, free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -27158,7 +27434,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); zval_ptr_dtor_nogc(free_op2); @@ -28549,7 +28833,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -28580,13 +28863,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -29044,18 +29323,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_VAR_UNUSED_HANDLER( count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -29136,6 +29417,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -29162,8 +29445,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -29200,7 +29489,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -29639,6 +29931,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -29663,8 +29957,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -29678,7 +29978,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -29705,6 +30008,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -29729,8 +30034,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -29743,7 +30054,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -29940,6 +30254,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA USE_OPLINE zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -29964,8 +30280,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -30055,7 +30372,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -30074,6 +30401,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA USE_OPLINE zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -30098,8 +30427,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -30189,7 +30519,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -30208,6 +30548,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA USE_OPLINE zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -30232,8 +30574,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -30323,7 +30666,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -30342,6 +30695,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA USE_OPLINE zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -30366,8 +30721,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -30457,7 +30813,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -31277,7 +31643,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -31308,13 +31673,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -31531,7 +31892,7 @@ num_index_dim: if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -31547,6 +31908,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER( zend_free_op free_op1; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -31566,7 +31928,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER( break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -31858,6 +32228,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND USE_OPLINE zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -31891,9 +32262,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -31914,7 +32286,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -31974,6 +32346,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -32000,8 +32374,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -32038,7 +32418,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -32153,6 +32536,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -32177,8 +32562,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -32192,7 +32583,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -32219,6 +32613,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -32243,8 +32639,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -32257,7 +32659,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -32318,9 +32723,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_U /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -32339,17 +32746,17 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_U Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -32357,11 +32764,18 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_U } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -32460,9 +32874,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -32481,17 +32897,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -32499,9 +32915,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -32556,6 +32978,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -32580,8 +33004,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -32671,7 +33096,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -32690,6 +33125,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -32714,8 +33151,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -32805,7 +33243,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -32824,6 +33272,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -32848,8 +33298,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -32939,7 +33390,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -32958,6 +33419,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -32982,8 +33445,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33073,7 +33537,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -33427,7 +33901,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -33554,7 +34027,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -33585,13 +34057,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -33727,6 +34195,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HA zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -33746,7 +34215,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HA break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -33760,6 +34237,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -33784,9 +34262,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -33943,6 +34431,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -33969,8 +34459,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -34007,7 +34503,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -34122,6 +34621,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -34146,8 +34647,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -34161,7 +34668,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -34189,6 +34699,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -34213,8 +34725,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -34227,7 +34745,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -34289,9 +34810,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -34310,17 +34833,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -34328,11 +34851,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -34431,9 +34961,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -34452,17 +34984,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -34470,9 +35002,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -34527,6 +35065,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ USE_OPLINE zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -34551,8 +35091,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -34642,7 +35183,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -34661,6 +35212,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ USE_OPLINE zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -34685,8 +35238,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -34776,7 +35330,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -34795,6 +35359,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ USE_OPLINE zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -34819,8 +35385,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -34910,7 +35477,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -34929,6 +35506,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ USE_OPLINE zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -34953,8 +35532,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35044,7 +35624,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -35399,7 +35989,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -35526,7 +36115,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -35557,13 +36145,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -35612,6 +36196,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_H zend_free_op free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -35631,7 +36216,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_H break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); zval_ptr_dtor_nogc(free_op2); @@ -35646,6 +36239,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -35670,9 +36264,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: zval_ptr_dtor_nogc(free_op2); @@ -36080,7 +36684,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -36111,13 +36714,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -36586,6 +37185,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -36612,8 +37213,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -36650,7 +37257,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -36765,6 +37375,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -36789,8 +37401,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -36804,7 +37422,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -36831,6 +37452,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -36855,8 +37478,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -36869,7 +37498,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -36930,9 +37562,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -36951,17 +37585,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -36969,11 +37603,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -37072,9 +37713,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -37093,17 +37736,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -37111,9 +37754,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -37168,6 +37817,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -37192,8 +37843,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -37283,7 +37935,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -37302,6 +37964,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -37326,8 +37990,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -37417,7 +38082,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -37436,6 +38111,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -37460,8 +38137,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -37551,7 +38229,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -37570,6 +38258,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -37594,8 +38284,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -37685,7 +38376,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -38039,7 +38740,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -38166,7 +38866,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -38197,13 +38896,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -38252,6 +38947,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDL zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -38271,7 +38967,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -38285,6 +38989,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -38309,9 +39014,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -39400,6 +40115,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC USE_OPLINE zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -39433,9 +40149,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -39456,7 +40173,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39639,20 +40356,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_CV != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { @@ -40041,8 +40765,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP } zval_ptr_dtor(&tmp); } - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } @@ -40878,6 +41602,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -40904,8 +41630,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -40942,7 +41674,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -41475,6 +42210,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -41499,8 +42236,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -41514,7 +42257,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -41541,6 +42287,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -41565,8 +42313,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -41579,7 +42333,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -41756,9 +42513,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_C /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -41777,17 +42536,17 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_C Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -41795,11 +42554,18 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_C } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -41898,9 +42664,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -41919,17 +42687,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -41937,9 +42705,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -41994,6 +42768,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -42018,8 +42794,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -42109,7 +42886,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -42128,6 +42915,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -42152,8 +42941,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -42243,7 +43033,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -42262,6 +43062,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -42286,8 +43088,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -42377,7 +43180,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -42396,6 +43209,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -42420,8 +43235,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -42511,7 +43327,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -43419,7 +44245,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -43660,7 +44485,7 @@ num_index_dim: if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -43676,6 +44501,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(opline->op1.var EXECUTE_DATA_CC); @@ -43695,7 +44521,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -43789,6 +44623,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); @@ -43813,9 +44648,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -44986,6 +45831,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -45012,8 +45859,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -45050,7 +45903,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -45585,6 +46441,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -45609,8 +46467,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -45624,7 +46488,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -45652,6 +46519,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -45676,8 +46545,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -45690,7 +46565,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -45868,9 +46746,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -45889,17 +46769,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -45907,11 +46787,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -46010,9 +46897,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -46031,17 +46920,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -46049,9 +46938,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -46106,6 +47001,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D USE_OPLINE zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -46130,8 +47027,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -46221,7 +47119,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -46240,6 +47148,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D USE_OPLINE zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -46264,8 +47174,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -46355,7 +47266,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -46374,6 +47295,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D USE_OPLINE zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -46398,8 +47321,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -46489,7 +47413,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -46508,6 +47442,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D USE_OPLINE zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -46532,8 +47468,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -46623,7 +47560,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -47475,7 +48422,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -47716,7 +48662,7 @@ num_index_dim: if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -47733,6 +48679,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDL zend_free_op free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(opline->op1.var EXECUTE_DATA_CC); @@ -47752,7 +48699,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); zval_ptr_dtor_nogc(free_op2); @@ -47847,6 +48802,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); @@ -47871,9 +48827,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: zval_ptr_dtor_nogc(free_op2); @@ -50021,18 +50987,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -50850,6 +51818,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -50876,8 +51846,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -50914,7 +51890,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -51353,6 +52332,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -51377,8 +52358,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -51392,7 +52379,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -51419,6 +52409,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -51443,8 +52435,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -51457,7 +52455,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -51634,9 +52635,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -51655,17 +52658,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -51673,11 +52676,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -51776,9 +52786,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -51797,17 +52809,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -51815,9 +52827,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -51872,6 +52890,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -51896,8 +52916,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -51987,7 +53008,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -52006,6 +53037,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -52030,8 +53063,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -52121,7 +53155,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -52140,6 +53184,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -52164,8 +53210,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -52255,7 +53302,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -52274,6 +53331,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -52298,8 +53357,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -52389,7 +53449,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -53336,7 +54406,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -53577,7 +54646,7 @@ num_index_dim: if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -53593,6 +54662,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(Z zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(opline->op1.var EXECUTE_DATA_CC); @@ -53612,7 +54682,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(Z break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -53706,6 +54784,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); @@ -53730,9 +54809,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: |