From c7f695f311541422beee14f3c262a9954d14d699 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 5 Dec 2014 12:40:47 +0300 Subject: [PATCH] Get rid of duplicate handlers (where the code for IS_TMP_VAR and IS_VAR operands is the same) --- Zend/zend_vm_def.h | 87 +- Zend/zend_vm_execute.h | 33864 +++++++++++++++++---------------------- Zend/zend_vm_gen.php | 4 +- 3 files changed, 14457 insertions(+), 19498 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 42b2acf698..005d78584f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -655,7 +655,7 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_BW_XOR, VAR|UNUSED|CV, CONST|TMP|VAR|UNUSED|CV) } } -ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV, incdec_t incdec_op) +ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, incdec_t incdec_op) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -736,17 +736,17 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR| ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_pre_incdec_property_helper, incdec_op, increment_function); } -ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_pre_incdec_property_helper, incdec_op, decrement_function); } -ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV, incdec_t incdec_op) +ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, incdec_t incdec_op) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -821,12 +821,12 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_post_incdec_property_helper, incdec_op, increment_function); } -ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_post_incdec_property_helper, incdec_op, decrement_function); } @@ -1013,7 +1013,7 @@ ZEND_VM_HANDLER(41, ZEND_PRINT, CONST|TMP|VAR|CV, ANY) ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ECHO); } -ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|VAR, int type) +ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR, int type) { USE_OPLINE zend_free_op free_op1; @@ -1125,22 +1125,22 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST| ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) +ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMPVAR|CV, UNUSED|CONST|VAR) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_R); } -ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) +ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMPVAR|CV, UNUSED|CONST|VAR) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_W); } -ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) +ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED|CONST|VAR) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_RW); } -ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) +ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CONST|VAR) { USE_OPLINE @@ -1151,12 +1151,12 @@ ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) } } -ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) +ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMPVAR|CV, UNUSED|CONST|VAR) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_UNSET); } -ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) +ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED|CONST|VAR) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_IS); } @@ -1296,7 +1296,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1; @@ -1351,7 +1351,7 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -1376,7 +1376,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -1400,7 +1400,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1; @@ -1454,7 +1454,7 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zval *container; @@ -1487,7 +1487,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP| } } -ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -1543,7 +1543,7 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_LIST, CONST|TMP|VAR|CV, CONST) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -2042,7 +2042,7 @@ ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP|UNUSED, CONST) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP|UNUSED, TMP|VAR|CV) +ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP|UNUSED, TMPVAR|CV) { USE_OPLINE zend_free_op free_op2; @@ -2060,15 +2060,10 @@ ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP|UNUSED, TMP|VAR|CV) } if (Z_TYPE_P(var) != IS_STRING) { - if (OP2_TYPE != IS_TMP_VAR) { - ZVAL_DEREF(var); - } - if (Z_TYPE_P(var) != IS_STRING) { - use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); + use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); - if (use_copy) { - var = &var_copy; - } + if (use_copy) { + var = &var_copy; } } add_string_to_string(str, str, var); @@ -2128,7 +2123,7 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMP|VAR|UNUSED|CV) } } -ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zval *function_name; @@ -2237,7 +2232,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUSED|CV) +ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSED|CV) { USE_OPLINE zval *function_name; @@ -3030,7 +3025,7 @@ ZEND_VM_HANDLER(117, ZEND_SEND_VAR, VAR|CV, ANY) varptr = GET_OP1_ZVAL_PTR(BP_VAR_R); arg = ZEND_CALL_ARG(EX(call), opline->op2.num); ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && Z_ISREF_P(varptr)) { + if (Z_ISREF_P(varptr)) { ZVAL_COPY(arg, Z_REFVAL_P(varptr)); FREE_OP1(); } else { @@ -3129,7 +3124,7 @@ ZEND_VM_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, ANY) varptr = GET_OP1_ZVAL_PTR(BP_VAR_R); arg = ZEND_CALL_ARG(EX(call), opline->op2.num); ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && Z_ISREF_P(varptr)) { + if (Z_ISREF_P(varptr)) { ZVAL_COPY(arg, Z_REFVAL_P(varptr)); FREE_OP1(); } else { @@ -3588,7 +3583,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMP|VAR|CV, ANY) +ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY) { USE_OPLINE zend_free_op free_op1; @@ -3645,7 +3640,7 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST) ZEND_VM_JMP(opline->op1.jmp_addr); } -ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -3881,7 +3876,7 @@ ZEND_VM_C_LABEL(constant_fetch_end): ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUSED|CV) +ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|CV) { USE_OPLINE zend_free_op free_op1; @@ -3969,7 +3964,7 @@ ZEND_VM_C_LABEL(str_index): ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|UNUSED|CV) +ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV) { zval *array; uint32_t size; @@ -4102,7 +4097,7 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY) +ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY) { USE_OPLINE zend_op_array *new_op_array=NULL; @@ -4228,7 +4223,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) +ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR) { USE_OPLINE zval tmp, *varname; @@ -4303,7 +4298,7 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -4388,7 +4383,7 @@ ZEND_VM_C_LABEL(num_index_dim): ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -4857,7 +4852,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) } } -ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) +ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR) { USE_OPLINE zval *value; @@ -4929,7 +4924,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) } } -ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -5010,7 +5005,7 @@ ZEND_VM_C_LABEL(num_index_prop): result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (OP2_TYPE == IS_CV || OP2_TYPE == IS_VAR) { + if (OP2_TYPE & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -5043,7 +5038,7 @@ ZEND_VM_C_LABEL(num_index_prop): ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -5084,7 +5079,7 @@ ZEND_VM_HANDLER(79, ZEND_EXIT, CONST|TMP|VAR|UNUSED|CV, ANY) SAVE_OPLINE(); if (OP1_TYPE != IS_UNUSED) { zend_free_op free_op1; - zval *ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); + zval *ptr = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); if (Z_TYPE_P(ptr) == IS_LONG) { EG(exit_status) = Z_LVAL_P(ptr); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 89c220aef1..4262329143 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4769,7 +4769,7 @@ num_index_prop: result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + if (IS_CONST & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -5229,808 +5229,260 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OP ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *container; zend_free_op free_op2; - zval *offset; - - SAVE_OPLINE(); - container = opline->op1.zv; - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - - if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_TMP_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + zval *function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zend_fcall_info_cache fcc; + char *error = NULL; + zend_function *func; + zend_class_entry *called_scope; + zend_object *object; - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); + if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error TSRMLS_CC)) { + if (error) { + efree(error); + } + func = fcc.function_handler; + if (func->common.fn_flags & ZEND_ACC_CLOSURE) { + /* Delay closure destruction until its invocation */ + func->common.prototype = (zend_function*)Z_OBJ_P(function_name); + Z_ADDREF_P(function_name); + } + called_scope = fcc.called_scope; + object = fcc.object; + if (object) { + GC_REFCOUNT(object)++; /* For $this pointer */ + } else if (func->common.scope && + !(func->common.fn_flags & ZEND_ACC_STATIC)) { + if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + func->common.scope->name->val, func->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + func->common.scope->name->val, func->common.function_name->val); } - } while (0); + } + } else { + zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(opline->op1.zv), error); + efree(error); + func = (zend_function*)&zend_pass_function; + called_scope = NULL; + object = NULL; } - zval_ptr_dtor_nogc(free_op2); + EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + func, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; - zval *offset; - - SAVE_OPLINE(); - container = opline->op1.zv; - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - - if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; + /* The generator object is stored in EX(return_value) */ + zend_generator *generator = (zend_generator *) EX(return_value); - /* here we are sure we are dealing with an object */ - do { - if (IS_TMP_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); - } + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value; -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1, free_op2; - zval *property; + value = opline->op1.zv; + ZVAL_COPY_VALUE(&generator->value, value); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - container = NULL; + /* Temporary variables don't need ctor copying */ + if (IS_CONST != IS_TMP_VAR) { + zval_opt_copy_ctor(&generator->value); + } + } else { + zval *value_ptr = NULL; - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } else { - return ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + } else { + ZVAL_MAKE_REF(value_ptr); + } + ZVAL_COPY(&generator->value, value_ptr); -static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *function_name; - zend_class_entry *ce; - zend_object *object; - zend_function *fbc; + } + } else { + zval *value = opline->op1.zv; - SAVE_OPLINE(); + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST) { + ZVAL_DUP(&generator->value, value); + } else if (IS_CONST == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) { + ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - if (IS_CONST == IS_CONST) { - /* no function found. try a static method in class */ - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CONST == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); } } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } - if (IS_CONST == IS_CONST && - IS_TMP_VAR == IS_CONST && - CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else if (IS_CONST != IS_CONST && - IS_TMP_VAR == IS_CONST && - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) { - /* do nothing */ - } else if (IS_TMP_VAR != IS_UNUSED) { + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - if (IS_TMP_VAR != IS_CONST) { - if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Function name must be a string"); - } - } + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_DUP(&generator->key, key); + } else if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->key, key); + } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { + ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - if (ce->get_static_method) { - fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC); } else { - fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - } - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_TMP_VAR == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { - if (IS_CONST == IS_CONST) { - CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc); - } else { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc); + ZVAL_COPY_VALUE(&generator->key, key); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); } } - if (IS_TMP_VAR != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); - } - } else { - if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); - } - if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); - } - fbc = ce->constructor; - } - object = NULL; - if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_OBJ(EX(This))) { - object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; - } - if (!object || - !instanceof_function(object->ce, ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); - } + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); } - if (IS_CONST != IS_CONST) { - /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EX(called_scope); - } + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; } - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); - if (IS_TMP_VAR == IS_UNUSED) { - EX(call)->return_value = NULL; - } + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POW_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - zend_fcall_info_cache fcc; - char *error = NULL; - zend_function *func; - zend_class_entry *called_scope; - zend_object *object; - - if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error TSRMLS_CC)) { - if (error) { - efree(error); - } - func = fcc.function_handler; - if (func->common.fn_flags & ZEND_ACC_CLOSURE) { - /* Delay closure destruction until its invocation */ - func->common.prototype = (zend_function*)Z_OBJ_P(function_name); - Z_ADDREF_P(function_name); - } - called_scope = fcc.called_scope; - object = fcc.object; - if (object) { - GC_REFCOUNT(object)++; /* For $this pointer */ - } else if (func->common.scope && - !(func->common.fn_flags & ZEND_ACC_STATIC)) { - if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, - "Non-static method %s::%s() should not be called statically", - func->common.scope->name->val, func->common.function_name->val); - } else { - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically", - func->common.scope->name->val, func->common.function_name->val); - } - } - } else { - zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(opline->op1.zv), error); - efree(error); - func = (zend_function*)&zend_pass_function; - called_scope = NULL; - object = NULL; - } - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - func, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); + SAVE_OPLINE(); + pow_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - fast_equal_function(result, - opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + fast_mod_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *expr_ptr, new_expr; + zend_free_op free_op2; SAVE_OPLINE(); - if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); - } - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); - - } else { - expr_ptr = opline->op1.zv; - if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } else if (IS_CONST == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } - } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(expr_ptr)) { - expr_ptr = Z_REFVAL_P(expr_ptr); - if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); - - } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } - } - - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - zend_string *str; - zend_ulong hval; + shift_left_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); -add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; - } - zval_ptr_dtor_nogc(free_op2); - } else { - zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); - } + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE + zend_free_op free_op2; - array = EX_VAR(opline->result.var); - if (IS_CONST != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_NEW_ARR(array); - zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); - - if (IS_CONST != IS_UNUSED) { - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init(Z_ARRVAL_P(array), 0); - } - } + SAVE_OPLINE(); + shift_right_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - if (IS_CONST == IS_UNUSED) { - ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_CONST != IS_UNUSED - } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#endif - } + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *container; - int result; - zend_ulong hval; - zval *offset; SAVE_OPLINE(); - container = opline->op1.zv; - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - - if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); - zval *value; - zend_string *str; - -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } - } -str_index_prop: - value = zend_hash_find_ind(ht, str); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - value = NULL; - break; - } - } - - if (opline->extended_value & ZEND_ISSET) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); - } - } else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { - result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check element of non-array"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ - zval tmp; - - result = 0; - if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(offset); - } - if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ - || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ - && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { - ZVAL_DUP(&tmp, offset); - convert_to_long(&tmp); - offset = &tmp; - } - } - if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { - if ((opline->extended_value & ZEND_ISSET) || - Z_STRVAL_P(container)[offset->value.lval] != '0') { - result = 1; - } - } - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); - } - - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *container; - int result; - zval *offset; - - SAVE_OPLINE(); - container = opline->op1.zv; - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - - if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); - } - - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - /* The generator object is stored in EX(return_value) */ - zend_generator *generator = (zend_generator *) EX(return_value); - - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_CONST != IS_UNUSED) { - - - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = opline->op1.zv; - ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CONST != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); - } - } else { - zval *value_ptr = NULL; - - if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); - } - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - } else { - ZVAL_MAKE_REF(value_ptr); - } - ZVAL_COPY(&generator->value, value_ptr); - - } - } else { - zval *value = opline->op1.zv; - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->value, value); - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - -static int ZEND_FASTCALL ZEND_POW_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - - SAVE_OPLINE(); - pow_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - - SAVE_OPLINE(); - fast_mod_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - - SAVE_OPLINE(); - shift_left_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - - SAVE_OPLINE(); - shift_right_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - - SAVE_OPLINE(); - concat_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + concat_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); @@ -6342,149 +5794,537 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OP ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *container; zend_free_op free_op2; - zval *offset; - - SAVE_OPLINE(); - container = opline->op1.zv; - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + zval *function_name = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + zend_fcall_info_cache fcc; + char *error = NULL; + zend_function *func; + zend_class_entry *called_scope; + zend_object *object; - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); + if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error TSRMLS_CC)) { + if (error) { + efree(error); + } + func = fcc.function_handler; + if (func->common.fn_flags & ZEND_ACC_CLOSURE) { + /* Delay closure destruction until its invocation */ + func->common.prototype = (zend_function*)Z_OBJ_P(function_name); + Z_ADDREF_P(function_name); + } + called_scope = fcc.called_scope; + object = fcc.object; + if (object) { + GC_REFCOUNT(object)++; /* For $this pointer */ + } else if (func->common.scope && + !(func->common.fn_flags & ZEND_ACC_STATIC)) { + if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + func->common.scope->name->val, func->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + func->common.scope->name->val, func->common.function_name->val); } - } while (0); + } + } else { + zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(opline->op1.zv), error); + efree(error); + func = (zend_function*)&zend_pass_function; + called_scope = NULL; + object = NULL; } - zval_ptr_dtor_nogc(free_op2); + EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + func, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval tmp, *varname; + HashTable *target_symbol_table; - zval *container; - zend_free_op free_op2; - zval *offset; SAVE_OPLINE(); - container = opline->op1.zv; - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; + if (IS_CONST == IS_CV && + IS_VAR == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + zval *var = EX_VAR(opline->op1.var); - /* here we are sure we are dealing with an object */ - do { - if (IS_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); + if (Z_REFCOUNTED_P(var)) { + zend_refcounted *garbage = Z_COUNTED_P(var); - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } + if (!--GC_REFCOUNT(garbage)) { + ZVAL_UNDEF(var); + _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); + } else { + GC_ZVAL_CHECK_POSSIBLE_ROOT(var); + ZVAL_UNDEF(var); } + } else { + ZVAL_UNDEF(var); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + varname = opline->op1.zv; - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); + ZVAL_UNDEF(&tmp); + if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } + + if (IS_VAR != IS_UNUSED) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); } - } while (0); + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } - zval_ptr_dtor_nogc(free_op2); + if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1, free_op2; - zval *property; - - SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - container = NULL; + zval *value; + SAVE_OPLINE(); + if (IS_CONST == IS_CV && + IS_VAR == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); + } else { + + zval tmp, *varname = opline->op1.zv; + + ZVAL_UNDEF(&tmp); + if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } + + if (IS_VAR != IS_UNUSED) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); + } + + if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } +} + +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in EX(return_value) */ + zend_generator *generator = (zend_generator *) EX(return_value); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ZVAL_COPY_VALUE(&generator->value, value); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + + /* Temporary variables don't need ctor copying */ + if (IS_CONST != IS_TMP_VAR) { + zval_opt_copy_ctor(&generator->value); + } + } else { + zval *value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + } else { + ZVAL_MAKE_REF(value_ptr); + } + ZVAL_COPY(&generator->value, value_ptr); + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST) { + ZVAL_DUP(&generator->value, value); + } else if (IS_CONST == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) { + ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CONST == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_DUP(&generator->key, key); + } else if (IS_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->key, key); + } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { + ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + zval_ptr_dtor_nogc(free_op2); + } else { + ZVAL_COPY_VALUE(&generator->key, key); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + } + } + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static int ZEND_FASTCALL ZEND_POW_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + + SAVE_OPLINE(); + pow_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *varname; + zval *retval; + zend_string *name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + varname = opline->op1.zv; + + if (IS_CONST == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + zend_string_addref(name); + } else { + name = zval_get_string(varname); + } + + if (IS_UNUSED != IS_UNUSED) { + zend_class_entry *ce; + + if (IS_UNUSED == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + if (IS_CONST != IS_CONST) { + zend_string_release(name); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + retval = zend_std_get_static_property(ce, name, 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + retval = zend_hash_find(target_symbol_table, name); + if (retval == NULL) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } + } + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { + if (Z_CONSTANT_P(retval)) { + zval_update_constant(retval, 1 TSRMLS_CC); + } + } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + + } + } + + if (IS_CONST != IS_CONST) { + zend_string_release(name); + } + + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zend_free_op free_op1; + + SAVE_OPLINE(); + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } + container = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + } else { - return ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (IS_UNUSED == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = opline->op1.zv; + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -6513,18 +6353,18 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE } if (IS_CONST == IS_CONST && - IS_VAR == IS_CONST && + IS_UNUSED == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else if (IS_CONST != IS_CONST && - IS_VAR == IS_CONST && + IS_UNUSED == IS_CONST && (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) { /* do nothing */ - } else if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; + } else if (IS_UNUSED != IS_UNUSED) { - function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_VAR != IS_CONST) { + + function_name = NULL; + if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -6536,12 +6376,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE if (ce->get_static_method) { fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC); } else { - fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); } if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); } - if (IS_VAR == IS_CONST && + if (IS_UNUSED == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { @@ -6550,8 +6390,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc); } } - if (IS_VAR != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + if (IS_UNUSED != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -6600,7 +6440,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); - if (IS_VAR == IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { EX(call)->return_value = NULL; } @@ -6608,77 +6448,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *function_name = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); - zend_fcall_info_cache fcc; - char *error = NULL; - zend_function *func; - zend_class_entry *called_scope; - zend_object *object; - - if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error TSRMLS_CC)) { - if (error) { - efree(error); - } - func = fcc.function_handler; - if (func->common.fn_flags & ZEND_ACC_CLOSURE) { - /* Delay closure destruction until its invocation */ - func->common.prototype = (zend_function*)Z_OBJ_P(function_name); - Z_ADDREF_P(function_name); - } - called_scope = fcc.called_scope; - object = fcc.object; - if (object) { - GC_REFCOUNT(object)++; /* For $this pointer */ - } else if (func->common.scope && - !(func->common.fn_flags & ZEND_ACC_STATIC)) { - if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, - "Non-static method %s::%s() should not be called statically", - func->common.scope->name->val, func->common.function_name->val); - } else { - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically", - func->common.scope->name->val, func->common.function_name->val); - } - } - } else { - zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(opline->op1.zv), error); - efree(error); - func = (zend_function*)&zend_pass_function; - called_scope = NULL; - object = NULL; - } - - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - func, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_equal_function(result, - opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -6713,9 +6483,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC } } - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if (IS_UNUSED != IS_UNUSED) { + + zval *offset = NULL; zend_string *str; zend_ulong hval; @@ -6731,7 +6501,7 @@ num_index: break; case IS_STRING: str = Z_STR_P(offset); - if (IS_VAR != IS_CONST) { + if (IS_UNUSED != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index; } @@ -6758,7 +6528,7 @@ str_index: /* do nothing */ break; } - zval_ptr_dtor_nogc(free_op2); + } else { zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } @@ -6766,7 +6536,7 @@ str_index: ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -6792,12 +6562,12 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAN ZEND_VM_NEXT_OPCODE(); #if 0 || IS_CONST != IS_UNUSED } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #endif } } -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval tmp, *varname; @@ -6806,7 +6576,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); if (IS_CONST == IS_CV && - IS_VAR == IS_UNUSED && + IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { zval *var = EX_VAR(opline->op1.var); @@ -6835,10 +6605,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND varname = &tmp; } - if (IS_VAR != IS_UNUSED) { + if (IS_UNUSED != IS_UNUSED) { zend_class_entry *ce; - if (IS_VAR == IS_CONST) { + if (IS_UNUSED == IS_CONST) { if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else { @@ -6872,14 +6642,14 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; SAVE_OPLINE(); if (IS_CONST == IS_CV && - IS_VAR == IS_UNUSED && + IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { value = EX_VAR(opline->op1.var); if (opline->extended_value & ZEND_ISSET) { @@ -6902,10 +6672,10 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC varname = &tmp; } - if (IS_VAR != IS_UNUSED) { + if (IS_UNUSED != IS_UNUSED) { zend_class_entry *ce; - if (IS_VAR == IS_CONST) { + if (IS_UNUSED == IS_CONST) { if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else { @@ -6943,154 +6713,32 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC } } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *container; - int result; - zend_ulong hval; - zval *offset; + zval *zfunc; + int closure_is_static, closure_is_being_defined_inside_static_context; SAVE_OPLINE(); - container = opline->op1.zv; - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); - zval *value; - zend_string *str; - -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } - } -str_index_prop: - value = zend_hash_find_ind(ht, str); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - value = NULL; - break; - } - } - - if (opline->extended_value & ZEND_ISSET) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); - } - } else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { - result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check element of non-array"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ - zval tmp; - - result = 0; - if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(offset); - } - if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ - || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ - && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { - ZVAL_DUP(&tmp, offset); - convert_to_long(&tmp); - offset = &tmp; - } - } - if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { - if ((opline->extended_value & ZEND_ISSET) || - Z_STRVAL_P(container)[offset->value.lval] != '0') { - result = 1; - } - } - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + if (UNEXPECTED((zfunc = zend_hash_find(EG(function_table), Z_STR_P(opline->op1.zv))) == NULL) || + UNEXPECTED(Z_FUNC_P(zfunc)->type != ZEND_USER_FUNCTION)) { + zend_error_noreturn(E_ERROR, "Base lambda function for closure not found"); } - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *container; - int result; - zval *offset; - - SAVE_OPLINE(); - container = opline->op1.zv; - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } + closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC; + closure_is_being_defined_inside_static_context = EX(func)->common.fn_flags & ZEND_ACC_STATIC; + if (closure_is_static || closure_is_being_defined_inside_static_context) { + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(called_scope), NULL TSRMLS_CC); } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(scope), Z_OBJ(EX(This)) ? &EX(This) : NULL TSRMLS_CC); } - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -7171,21 +6819,21 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ } /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { + if (IS_UNUSED == IS_CONST) { ZVAL_DUP(&generator->key, key); - } else if (IS_VAR == IS_TMP_VAR) { + } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { + } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); + } else { ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { + if (IS_UNUSED == IS_CV) { if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); } } @@ -7221,1146 +6869,402 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_POW_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + SAVE_OPLINE(); - pow_function(EX_VAR(opline->result.var), + fast_add_function(EX_VAR(opline->result.var), opline->op1.zv, - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varname; - zval *retval; - zend_string *name; - HashTable *target_symbol_table; SAVE_OPLINE(); - varname = opline->op1.zv; - - if (IS_CONST == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - zend_string_addref(name); - } else { - name = zval_get_string(varname); - } + fast_sub_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - if (IS_CONST != IS_CONST) { - zend_string_release(name); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - retval = zend_std_get_static_property(ce, name, 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); +static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - retval = zend_hash_find(target_symbol_table, name); - if (retval == NULL) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1 TSRMLS_CC); - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - } - } + SAVE_OPLINE(); + fast_mul_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - if (IS_CONST != IS_CONST) { - zend_string_release(name); - } - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { - ZVAL_UNREF(retval); - } - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + USE_OPLINE -static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} -static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + SAVE_OPLINE(); + fast_div_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + + SAVE_OPLINE(); + fast_mod_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + USE_OPLINE + + + SAVE_OPLINE(); + shift_left_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + USE_OPLINE + + + SAVE_OPLINE(); + shift_right_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op1; + SAVE_OPLINE(); + concat_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - container = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - } else { - if (IS_UNUSED == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - container = opline->op1.zv; - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + + SAVE_OPLINE(); + fast_is_identical_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; - zend_class_entry *ce; - zend_object *object; - zend_function *fbc; + + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); + fast_is_not_identical_function(result, + opline->op1.zv, + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - if (IS_CONST == IS_CONST) { - /* no function found. try a static method in class */ - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - } - if (IS_CONST == IS_CONST && - IS_UNUSED == IS_CONST && - CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else if (IS_CONST != IS_CONST && - IS_UNUSED == IS_CONST && - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) { - /* do nothing */ - } else if (IS_UNUSED != IS_UNUSED) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} +static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - function_name = NULL; - if (IS_UNUSED != IS_CONST) { - if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Function name must be a string"); - } - } + zval *result = EX_VAR(opline->result.var); - if (ce->get_static_method) { - fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC); - } else { - fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - } - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { - if (IS_CONST == IS_CONST) { - CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc); - } else { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc); - } - } - if (IS_UNUSED != IS_CONST) { + SAVE_OPLINE(); + fast_equal_function(result, + opline->op1.zv, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - } - } else { - if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); - } - if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); - } - fbc = ce->constructor; - } - object = NULL; - if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_OBJ(EX(This))) { - object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; - } - if (!object || - !instanceof_function(object->ce, ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); - } - } - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_CONST != IS_CONST) { - /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EX(called_scope); - } - } +static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_not_equal_function(result, + opline->op1.zv, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - if (IS_UNUSED == IS_UNUSED) { - EX(call)->return_value = NULL; - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); - } - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); - - } else { - expr_ptr = opline->op1.zv; - if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } else if (IS_CONST == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } - } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(expr_ptr)) { - expr_ptr = Z_REFVAL_P(expr_ptr); - if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); - - } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } - } - - if (IS_UNUSED != IS_UNUSED) { - - zval *offset = NULL; - zend_string *str; - zend_ulong hval; + fast_is_smaller_function(result, + opline->op1.zv, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); -add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_UNUSED != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; - } - } else { - zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zval *array; - uint32_t size; - USE_OPLINE - - array = EX_VAR(opline->result.var); - if (IS_CONST != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_NEW_ARR(array); - zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); - - if (IS_CONST != IS_UNUSED) { - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init(Z_ARRVAL_P(array), 0); - } - } - - if (IS_CONST == IS_UNUSED) { - ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_CONST != IS_UNUSED - } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#endif - } -} - -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval tmp, *varname; - HashTable *target_symbol_table; + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - if (IS_CONST == IS_CV && - IS_UNUSED == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - zval *var = EX_VAR(opline->op1.var); - - if (Z_REFCOUNTED_P(var)) { - zend_refcounted *garbage = Z_COUNTED_P(var); - - if (!--GC_REFCOUNT(garbage)) { - ZVAL_UNDEF(var); - _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); - } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); - } - } else { - ZVAL_UNDEF(var); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - varname = opline->op1.zv; - - ZVAL_UNDEF(&tmp); - if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); - } + fast_is_smaller_or_equal_function(result, + opline->op1.zv, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - - SAVE_OPLINE(); - if (IS_CONST == IS_CV && - IS_UNUSED == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - value = EX_VAR(opline->op1.var); - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !i_zend_is_true(value TSRMLS_CC)); - CHECK_EXCEPTION(); - } - ZEND_VM_NEXT_OPCODE(); - } else { - - zval tmp, *varname = opline->op1.zv; - - ZVAL_UNDEF(&tmp); - if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); - } - if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - value && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !value || !i_zend_is_true(value TSRMLS_CC)); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } -} - -static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *zfunc; - int closure_is_static, closure_is_being_defined_inside_static_context; SAVE_OPLINE(); + bitwise_or_function(EX_VAR(opline->result.var), + opline->op1.zv, + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - if (UNEXPECTED((zfunc = zend_hash_find(EG(function_table), Z_STR_P(opline->op1.zv))) == NULL) || - UNEXPECTED(Z_FUNC_P(zfunc)->type != ZEND_USER_FUNCTION)) { - zend_error_noreturn(E_ERROR, "Base lambda function for closure not found"); - } - - closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC; - closure_is_being_defined_inside_static_context = EX(func)->common.fn_flags & ZEND_ACC_STATIC; - if (closure_is_static || closure_is_being_defined_inside_static_context) { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(called_scope), NULL TSRMLS_CC); - } else { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(scope), Z_OBJ(EX(This)) ? &EX(This) : NULL TSRMLS_CC); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - /* The generator object is stored in EX(return_value) */ - zend_generator *generator = (zend_generator *) EX(return_value); - - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_CONST != IS_UNUSED) { - - - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = opline->op1.zv; - ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CONST != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); - } - } else { - zval *value_ptr = NULL; - - if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); - } - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - } else { - ZVAL_MAKE_REF(value_ptr); - } - ZVAL_COPY(&generator->value, value_ptr); - - } - } else { - zval *value = opline->op1.zv; - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->value, value); - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_UNUSED != IS_UNUSED) { - - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->key, key); - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - -static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); - fast_add_function(EX_VAR(opline->result.var), + bitwise_and_function(EX_VAR(opline->result.var), opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); - fast_sub_function(EX_VAR(opline->result.var), + bitwise_xor_function(EX_VAR(opline->result.var), opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); - fast_mul_function(EX_VAR(opline->result.var), + boolean_xor_function(EX_VAR(opline->result.var), opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *container; SAVE_OPLINE(); - fast_div_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + container = opline->op1.zv; + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *container; SAVE_OPLINE(); - fast_mod_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + container = opline->op1.zv; + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zval *container; + zend_free_op free_op1; SAVE_OPLINE(); - shift_left_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + container = NULL; + if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + + } else { + if (IS_CV == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = opline->op1.zv; + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *container; + + zval *offset; SAVE_OPLINE(); - shift_right_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + container = opline->op1.zv; + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + /* here we are sure we are dealing with an object */ + do { + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); -static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } + } + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - SAVE_OPLINE(); - concat_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } while (0); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - - SAVE_OPLINE(); - fast_is_identical_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_is_not_identical_function(result, - opline->op1.zv, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_equal_function(result, - opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_not_equal_function(result, - opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_is_smaller_function(result, - opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_is_smaller_or_equal_function(result, - opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - - SAVE_OPLINE(); - bitwise_or_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - - SAVE_OPLINE(); - bitwise_and_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - - SAVE_OPLINE(); - bitwise_xor_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - - SAVE_OPLINE(); - boolean_xor_function(EX_VAR(opline->result.var), - opline->op1.zv, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *container; - - SAVE_OPLINE(); - container = opline->op1.zv; - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *container; - - SAVE_OPLINE(); - container = opline->op1.zv; - zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - zend_free_op free_op1; - - SAVE_OPLINE(); - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - container = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - - - } else { - if (IS_CV == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - container = opline->op1.zv; - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - - - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *container; - - zval *offset; - - SAVE_OPLINE(); - container = opline->op1.zv; - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - - if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); - } - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8889,7 +7793,7 @@ num_index_prop: result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_CV == IS_CV || IS_CV == IS_VAR) { + if (IS_CV & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -9223,710 +8127,1117 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVAR_HANDLER(ZEN ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; + + zval *container; + zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); - bitwise_not_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + container = opline->op1.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); -static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; - SAVE_OPLINE(); - boolean_not_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + /* here we are sure we are dealing with an object */ + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); -static int ZEND_FASTCALL ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *z; + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } + } - SAVE_OPLINE(); - z = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - zend_print_variable(z TSRMLS_CC); + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } while (0); + } + + zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_PRINT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - ZVAL_LONG(EX_VAR(opline->result.var), 1); - return ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_JMPZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *val; + zval *container; + zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - if (IS_TMP_VAR == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } - } + container = opline->op1.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (i_zend_is_true(val TSRMLS_CC)) { - opline++; + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); } else { - opline = opline->op2.jmp_addr; - } - zval_ptr_dtor_nogc(free_op1); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline); -} + zval *retval; -static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *val; + /* here we are sure we are dealing with an object */ + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); - SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } + } - if (IS_TMP_VAR == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); - } - } + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - if (i_zend_is_true(val TSRMLS_CC)) { - opline = opline->op2.jmp_addr; - } else { - opline++; - } - zval_ptr_dtor_nogc(free_op1); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } while (0); } - ZEND_VM_JMP(opline); -} - -static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *val; - - SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - if (IS_TMP_VAR == IS_TMP_VAR) { - if (EXPECTED(Z_TYPE_P(val) == IS_TRUE)) { - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } - } + zval_ptr_dtor_nogc(free_op2); - if (i_zend_is_true(val TSRMLS_CC)) { - opline = (zend_op*)(((char*)opline) + opline->extended_value); - } else { - opline = opline->op2.jmp_addr; - } - zval_ptr_dtor_nogc(free_op1); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *val; + zval *container; - SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + /* Behave like FETCH_OBJ_W */ + zend_free_op free_op1, free_op2; + zval *property; - if (IS_TMP_VAR == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); + SAVE_OPLINE(); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + container = NULL; + + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - } - if (i_zend_is_true(val TSRMLS_CC)) { - zval_ptr_dtor_nogc(free_op1); - ZVAL_TRUE(EX_VAR(opline->result.var)); - opline++; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } else { - zval_ptr_dtor_nogc(free_op1); - ZVAL_FALSE(EX_VAR(opline->result.var)); - opline = opline->op2.jmp_addr; + return ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *val; + zval *function_name; + zend_class_entry *ce; + zend_object *object; + zend_function *fbc; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - if (IS_TMP_VAR == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); + if (IS_CONST == IS_CONST) { + /* no function found. try a static method in class */ + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); } - } - if (i_zend_is_true(val TSRMLS_CC)) { - ZVAL_TRUE(EX_VAR(opline->result.var)); - opline = opline->op2.jmp_addr; } else { - ZVAL_FALSE(EX_VAR(opline->result.var)); - opline++; - } - zval_ptr_dtor_nogc(free_op1); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + ce = Z_CE_P(EX_VAR(opline->op1.var)); } - ZEND_VM_JMP(opline); -} - -static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *retval_ptr; - zend_free_op free_op1; - SAVE_OPLINE(); - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + if (IS_CONST == IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && + CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else if (IS_CONST != IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && + (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) { + /* do nothing */ + } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zend_free_op free_op2; - if (!EX(return_value)) { - zval_ptr_dtor_nogc(free_op1); - } else { - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { - zval_copy_ctor_func(EX(return_value)); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } - } - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(retval_ptr)) { - ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr)); + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + } + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC); } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); - } + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); } - } - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *retval_ptr; - zend_free_op free_op1; - - SAVE_OPLINE(); - - do { - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR || - (IS_TMP_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { - /* Not supposed to happen, but we'll allow it */ - zend_error(E_NOTICE, "Only variable references should be returned by reference"); - - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - if (!EX(return_value)) { - if (IS_TMP_VAR == IS_TMP_VAR) { - zval_ptr_dtor_nogc(free_op1); - } + if (UNEXPECTED(fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + if (IS_CONST == IS_CONST) { + CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc); } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor_no_imm(EX(return_value)); - } + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc); } - break; - } - - retval_ptr = NULL; - - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - - if (IS_TMP_VAR == IS_VAR) { - if (retval_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { - zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); - } - break; - } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(free_op2); } - - if (EX(return_value)) { - ZVAL_MAKE_REF(retval_ptr); - Z_ADDREF_P(retval_ptr); - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - } while (0); - - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zend_free_op free_op1; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - if (IS_TMP_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } - zend_error_noreturn(E_ERROR, "Can only throw objects"); + fbc = ce->constructor; } - zend_exception_save(TSRMLS_C); - if (IS_TMP_VAR != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value); + object = NULL; + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); + GC_REFCOUNT(object)++; + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } + } } - zend_throw_exception_object(value TSRMLS_CC); - zend_exception_restore(TSRMLS_C); - - HANDLE_EXCEPTION(); -} - -static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value, *arg; - zend_free_op free_op1; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - arg = ZEND_CALL_ARG(EX(call), opline->op2.num); - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - ZVAL_COPY_VALUE(arg, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) { - zval_copy_ctor_func(arg); + if (IS_CONST != IS_CONST) { + /* previous opcode is ZEND_FETCH_CLASS */ + if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { + ce = EX(called_scope); } } - ZEND_VM_NEXT_OPCODE(); -} -static int ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value, *arg; - zend_free_op free_op1; + EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); - SAVE_OPLINE(); - if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num); - } - value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - arg = ZEND_CALL_ARG(EX(call), opline->op2.num); - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - ZVAL_COPY_VALUE(arg, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) { - zval_copy_ctor_func(arg); - } + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + EX(call)->return_value = NULL; } + + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BOOL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *retval = EX_VAR(opline->result.var); + zend_free_op free_op2; + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ - ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1) TSRMLS_CC)); - zval_ptr_dtor_nogc(free_op1); + fast_equal_function(result, + opline->op1.zv, + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *obj; - zend_class_entry *ce; - zend_function *clone; - zend_object_clone_obj_t clone_call; - SAVE_OPLINE(); - obj = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + zval *expr_ptr, new_expr; - if (IS_TMP_VAR == IS_CONST || - (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + SAVE_OPLINE(); + if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && + (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = NULL; + if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } - zend_error_noreturn(E_ERROR, "__clone method called on non-object"); - } + ZVAL_MAKE_REF(expr_ptr); + Z_ADDREF_P(expr_ptr); - ce = Z_OBJCE_P(obj); - clone = ce ? ce->clone : NULL; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; - if (UNEXPECTED(clone_call == NULL)) { - if (ce) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); - } else { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + } else { + expr_ptr = opline->op1.zv; + if (IS_CONST == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } else if (IS_CONST == IS_CONST) { + if (!Z_IMMUTABLE_P(expr_ptr)) { + ZVAL_DUP(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } + } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(expr_ptr)) { + expr_ptr = Z_REFVAL_P(expr_ptr); + if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); + + } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); } } - if (ce && clone) { - if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); - } - } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zend_free_op free_op2; + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zend_string *str; + zend_ulong hval; + +add_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + break; + case IS_STRING: + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index; + case IS_FALSE: + hval = 0; + goto num_index; + case IS_TRUE: + hval = 1; + goto num_index; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto add_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); + /* do nothing */ + break; } + zval_ptr_dtor_nogc(free_op2); + } else { + zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (EXPECTED(EG(exception) == NULL)) { - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj TSRMLS_CC)); - if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var))); +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + array = EX_VAR(opline->result.var); + if (IS_CONST != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + } else { + size = 0; + } + ZVAL_NEW_ARR(array); + zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); + + if (IS_CONST != IS_UNUSED) { + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init(Z_ARRVAL_P(array), 0); } } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (IS_CONST == IS_UNUSED) { + ZEND_VM_NEXT_OPCODE(); +#if 0 || IS_CONST != IS_UNUSED + } else { + return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +#endif + } } -static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *expr; - zval *result = EX_VAR(opline->result.var); + zend_free_op free_op2; + zval *container; + int result; + zend_ulong hval; + zval *offset; SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + container = opline->op1.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - switch (opline->extended_value) { - case IS_NULL: - /* This code is taken from convert_to_null. However, it does not seems very useful, - * because a conversion to null always results in the same value. This could only - * be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */ -#if 0 - if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { - ZVAL_DEREF(expr); + if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value; + zend_string *str; + +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } } - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) { - if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL TSRMLS_CC) == SUCCESS) { +str_index_prop: + value = zend_hash_find_ind(ht, str); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else { + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 1; + goto num_index_prop; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto isset_again; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + value = NULL; break; - } } -#endif + } - ZVAL_NULL(result); - break; - case _IS_BOOL: - ZVAL_BOOL(result, zend_is_true(expr TSRMLS_CC)); - break; - case IS_LONG: - ZVAL_LONG(result, zval_get_long(expr)); - break; - case IS_DOUBLE: - ZVAL_DOUBLE(result, zval_get_double(expr)); - break; - case IS_STRING: - ZVAL_STR(result, zval_get_string(expr)); - break; - default: - /* If value is already of correct type, return it directly */ - if (Z_TYPE_P(expr) == opline->extended_value) { - ZVAL_COPY_VALUE(result, expr); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) { - zval_copy_ctor_func(result); - } - } else if (IS_TMP_VAR != IS_TMP_VAR) { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } + if (opline->extended_value & ZEND_ISSET) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check element of non-array"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ + zval tmp; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) { + ZVAL_DEREF(offset); } - - if (opline->extended_value == IS_ARRAY) { - if (Z_TYPE_P(expr) != IS_OBJECT) { - ZVAL_NEW_ARR(result); - zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0); - if (Z_TYPE_P(expr) != IS_NULL) { - expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { - zval_copy_ctor_func(expr); - } - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } - } else { - ZVAL_COPY_VALUE(result, expr); - Z_ADDREF_P(result); - convert_to_array(result); - } - } else { - if (Z_TYPE_P(expr) != IS_ARRAY) { - object_init(result); - if (Z_TYPE_P(expr) != IS_NULL) { - expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { - zval_copy_ctor_func(expr); - } - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } - } else { - ZVAL_COPY_VALUE(result, expr); - zval_opt_copy_ctor(result); - convert_to_object(result); + if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ + || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ + && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { + ZVAL_DUP(&tmp, offset); + convert_to_long(&tmp); + offset = &tmp; + } + } + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { + if ((opline->extended_value & ZEND_ISSET) || + Z_STRVAL_P(container)[offset->value.lval] != '0') { + result = 1; } } + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_op_array *new_op_array=NULL; - zend_free_op free_op1; - zval *inc_filename; - zval tmp_inc_filename; - zend_bool failure_retval=0; + zend_free_op free_op2; + zval *container; + int result; + zval *offset; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp_inc_filename); - if (Z_TYPE_P(inc_filename) != IS_STRING) { - ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); - inc_filename = &tmp_inc_filename; - } + container = opline->op1.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) { - if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) { - zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { - zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; } } else { - switch (opline->extended_value) { - case ZEND_INCLUDE_ONCE: - case ZEND_REQUIRE_ONCE: { - zend_file_handle file_handle; - char *resolved_path; + result = ((opline->extended_value & ZEND_ISSET) == 0); + } - resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename) TSRMLS_CC); - if (resolved_path) { - failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path)); - } else { - resolved_path = Z_STRVAL_P(inc_filename); - } + zval_ptr_dtor_nogc(free_op2); + ZVAL_BOOL(EX_VAR(opline->result.var), result); - if (failure_retval) { - /* do nothing, file already included */ - } else if (SUCCESS == zend_stream_open(resolved_path, &file_handle TSRMLS_CC)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (!file_handle.opened_path) { - file_handle.opened_path = estrdup(resolved_path); - } +static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; - if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) { - new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC); - zend_destroy_file_handle(&file_handle TSRMLS_CC); - } else { - zend_file_handle_dtor(&file_handle TSRMLS_CC); - failure_retval=1; - } - } else { - if (opline->extended_value == ZEND_INCLUDE_ONCE) { - zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); - } else { - zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); - } - } - if (resolved_path != Z_STRVAL_P(inc_filename)) { - efree(resolved_path); - } - } - break; - case ZEND_INCLUDE: - case ZEND_REQUIRE: - new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC); - break; - case ZEND_EVAL: { - char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); + SAVE_OPLINE(); + bitwise_not_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - new_op_array = zend_compile_string(inc_filename, eval_desc TSRMLS_CC); - efree(eval_desc); - } - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) { - zend_string_release(Z_STR(tmp_inc_filename)); - } +static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + + SAVE_OPLINE(); + boolean_not_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } else if (EXPECTED(new_op_array != NULL)) { - zval *return_value = NULL; - zend_execute_data *call; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (RETURN_VALUE_USED(opline)) { - return_value = EX_VAR(opline->result.var); - } +static int ZEND_FASTCALL ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *z; - new_op_array->scope = EG(scope); /* ??? */ + SAVE_OPLINE(); + z = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, - (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL TSRMLS_CC); + zend_print_variable(z TSRMLS_CC); - if (EX(symbol_table)) { - call->symbol_table = EX(symbol_table); - } else { - call->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); - } + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - call->prev_execute_data = execute_data; - i_init_code_execute_data(call, new_op_array, return_value TSRMLS_CC); - if (EXPECTED(zend_execute_ex == execute_ex)) { - ZEND_VM_ENTER(); - } else { - ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); - zend_execute_ex(call TSRMLS_CC); - } +static int ZEND_FASTCALL ZEND_PRINT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - destroy_op_array(new_op_array TSRMLS_CC); - efree_size(new_op_array, sizeof(zend_op_array)); - if (UNEXPECTED(EG(exception) != NULL)) { - zend_throw_exception_internal(NULL TSRMLS_CC); - HANDLE_EXCEPTION(); + ZVAL_LONG(EX_VAR(opline->result.var), 1); + return ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_JMPZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *val; + + SAVE_OPLINE(); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + + if (IS_TMP_VAR == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); } + } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_BOOL(EX_VAR(opline->result.var), failure_retval); + if (i_zend_is_true(val TSRMLS_CC)) { + opline++; + } else { + opline = opline->op2.jmp_addr; } - ZEND_VM_NEXT_OPCODE(); + zval_ptr_dtor_nogc(free_op1); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *array_ptr, *array_ref, iterator, tmp; - HashTable *fe_ht; - zend_object_iterator *iter = NULL; - zend_class_entry *ce = NULL; - zend_bool is_empty = 0; + zval *val; SAVE_OPLINE(); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && - (opline->extended_value & ZEND_FE_FETCH_BYREF)) { - array_ptr = array_ref = NULL; - ZVAL_DEREF(array_ptr); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); - if (!Z_ISREF_P(array_ref)) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); - } - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce->get_iterator == NULL) { - Z_ADDREF_P(array_ptr); - } - array_ref = array_ptr; - } else { - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); + if (IS_TMP_VAR == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } + } + + if (i_zend_is_true(val TSRMLS_CC)) { + opline = opline->op2.jmp_addr; + } else { + opline++; + } + zval_ptr_dtor_nogc(free_op1); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); +} + +static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *val; + + SAVE_OPLINE(); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + + if (IS_TMP_VAR == IS_TMP_VAR) { + if (EXPECTED(Z_TYPE_P(val) == IS_TRUE)) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } + } + + if (i_zend_is_true(val TSRMLS_CC)) { + opline = (zend_op*)(((char*)opline) + opline->extended_value); + } else { + opline = opline->op2.jmp_addr; + } + zval_ptr_dtor_nogc(free_op1); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); +} + +static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *val; + + SAVE_OPLINE(); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + + if (IS_TMP_VAR == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } + } + + if (i_zend_is_true(val TSRMLS_CC)) { + zval_ptr_dtor_nogc(free_op1); + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline++; + } else { + zval_ptr_dtor_nogc(free_op1); + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline = opline->op2.jmp_addr; + } + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); +} + +static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *val; + + SAVE_OPLINE(); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + + if (IS_TMP_VAR == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } + } + if (i_zend_is_true(val TSRMLS_CC)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline = opline->op2.jmp_addr; + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline++; + } + zval_ptr_dtor_nogc(free_op1); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); +} + +static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zend_free_op free_op1; + + SAVE_OPLINE(); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + + if (!EX(return_value)) { + zval_ptr_dtor_nogc(free_op1); + } else { + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { + zval_copy_ctor_func(EX(return_value)); + } + } + } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(retval_ptr)) { + ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr)); + + } else { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + } + } + } + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zend_free_op free_op1; + + SAVE_OPLINE(); + + do { + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR || + (IS_TMP_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { + /* Not supposed to happen, but we'll allow it */ + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + + retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + if (!EX(return_value)) { + if (IS_TMP_VAR == IS_TMP_VAR) { + zval_ptr_dtor_nogc(free_op1); + } + } else { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + if (IS_TMP_VAR != IS_TMP_VAR) { + zval_opt_copy_ctor_no_imm(EX(return_value)); + } + } + break; + } + + retval_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); + } + + if (IS_TMP_VAR == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (EX(return_value)) { + ZVAL_NEW_REF(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + } + break; + } + } + + if (EX(return_value)) { + ZVAL_MAKE_REF(retval_ptr); + Z_ADDREF_P(retval_ptr); + ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + } + } while (0); + + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zend_free_op free_op1; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + + if (IS_TMP_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Can only throw objects"); + } + + zend_exception_save(TSRMLS_C); + if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + + zend_throw_exception_object(value TSRMLS_CC); + zend_exception_restore(TSRMLS_C); + + HANDLE_EXCEPTION(); +} + +static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + zend_free_op free_op1; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + arg = ZEND_CALL_ARG(EX(call), opline->op2.num); + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) { + zval_copy_ctor_func(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + zend_free_op free_op1; + + SAVE_OPLINE(); + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { + zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num); + } + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + arg = ZEND_CALL_ARG(EX(call), opline->op2.num); + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) { + zval_copy_ctor_func(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *obj; + zend_class_entry *ce; + zend_function *clone; + zend_object_clone_obj_t clone_call; + + SAVE_OPLINE(); + obj = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + + if (IS_TMP_VAR == IS_CONST || + (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "__clone method called on non-object"); + } + + ce = Z_OBJCE_P(obj); + clone = ce ? ce->clone : NULL; + clone_call = Z_OBJ_HT_P(obj)->clone_obj; + if (UNEXPECTED(clone_call == NULL)) { + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); + } else { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + } + } + + if (ce && clone) { + if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { + /* Ensure that if we're calling a private function, we're allowed to do so. + */ + if (UNEXPECTED(ce != EG(scope))) { + zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + } + } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { + /* Ensure that if we're calling a protected function, we're allowed to do so. + */ + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { + zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + } + } + } + + if (EXPECTED(EG(exception) == NULL)) { + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj TSRMLS_CC)); + if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var))); + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr; + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + + switch (opline->extended_value) { + case IS_NULL: + /* This code is taken from convert_to_null. However, it does not seems very useful, + * because a conversion to null always results in the same value. This could only + * be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */ +#if 0 + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(expr); + } + if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) { + if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL TSRMLS_CC) == SUCCESS) { + break; + } + } +#endif + + ZVAL_NULL(result); + break; + case _IS_BOOL: + ZVAL_BOOL(result, zend_is_true(expr TSRMLS_CC)); + break; + case IS_LONG: + ZVAL_LONG(result, zval_get_long(expr)); + break; + case IS_DOUBLE: + ZVAL_DOUBLE(result, zval_get_double(expr)); + break; + case IS_STRING: + ZVAL_STR(result, zval_get_string(expr)); + break; + default: + /* If value is already of correct type, return it directly */ + if (Z_TYPE_P(expr) == opline->extended_value) { + ZVAL_COPY_VALUE(result, expr); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) { + zval_copy_ctor_func(result); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + if (opline->extended_value == IS_ARRAY) { + if (Z_TYPE_P(expr) != IS_OBJECT) { + ZVAL_NEW_ARR(result); + zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0); + if (Z_TYPE_P(expr) != IS_NULL) { + expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { + zval_copy_ctor_func(expr); + } + } else { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + } + } else { + ZVAL_COPY_VALUE(result, expr); + Z_ADDREF_P(result); + convert_to_array(result); + } + } else { + if (Z_TYPE_P(expr) != IS_ARRAY) { + object_init(result); + if (Z_TYPE_P(expr) != IS_NULL) { + expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { + zval_copy_ctor_func(expr); + } + } else { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + } + } else { + ZVAL_COPY_VALUE(result, expr); + zval_opt_copy_ctor(result); + convert_to_object(result); + } + } + } + + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *array_ptr, *array_ref, iterator, tmp; + HashTable *fe_ht; + zend_object_iterator *iter = NULL; + zend_class_entry *ce = NULL; + zend_bool is_empty = 0; + + SAVE_OPLINE(); + + if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && + (opline->extended_value & ZEND_FE_FETCH_BYREF)) { + array_ptr = array_ref = NULL; + ZVAL_DEREF(array_ptr); + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + SEPARATE_ARRAY(array_ptr); + if (!Z_ISREF_P(array_ref)) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); + } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { + ce = Z_OBJCE_P(array_ptr); + if (ce->get_iterator == NULL) { + Z_ADDREF_P(array_ptr); + } + array_ref = array_ptr; + } else { + if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } } else { array_ptr = array_ref = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); @@ -10450,174 +9761,26 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *varname; - zval *retval; - zend_string *name; - HashTable *target_symbol_table; + zval *container; SAVE_OPLINE(); - varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (IS_TMP_VAR == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - zend_string_addref(name); - } else { - name = zval_get_string(varname); - } + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_CONST != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - if (IS_TMP_VAR != IS_CONST) { - zend_string_release(name); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - retval = zend_std_get_static_property(ce, name, 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - retval = zend_hash_find(target_symbol_table, name); - if (retval == NULL) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1 TSRMLS_CC); - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - zval_ptr_dtor_nogc(free_op1); - } - } - - if (IS_TMP_VAR != IS_CONST) { - zend_string_release(name); - } - - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { - ZVAL_UNREF(retval); - } - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); @@ -10981,21 +10144,6 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11115,153 +10263,6 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAN } } -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval tmp, *varname; - HashTable *target_symbol_table; - zend_free_op free_op1; - - SAVE_OPLINE(); - if (IS_TMP_VAR == IS_CV && - IS_CONST == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - zval *var = EX_VAR(opline->op1.var); - - if (Z_REFCOUNTED_P(var)) { - zend_refcounted *garbage = Z_COUNTED_P(var); - - if (!--GC_REFCOUNT(garbage)) { - ZVAL_UNDEF(var); - _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); - } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); - } - } else { - ZVAL_UNDEF(var); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_CONST != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_TMP_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_TMP_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - - SAVE_OPLINE(); - if (IS_TMP_VAR == IS_CV && - IS_CONST == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - value = EX_VAR(opline->op1.var); - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !i_zend_is_true(value TSRMLS_CC)); - CHECK_EXCEPTION(); - } - ZEND_VM_NEXT_OPCODE(); - } else { - zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_CONST != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_TMP_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - value && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !value || !i_zend_is_true(value TSRMLS_CC)); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } -} - static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11343,7 +10344,7 @@ num_index_prop: result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + if (IS_CONST & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -11809,584 +10810,409 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCO ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *container; - zend_free_op free_op2; - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; + /* The generator object is stored in EX(return_value) */ + zend_generator *generator = (zend_generator *) EX(return_value); - /* here we are sure we are dealing with an object */ - do { - if (IS_TMP_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); - } + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value; -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - zend_free_op free_op2; - zval *offset; + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + ZVAL_COPY_VALUE(&generator->value, value); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; + /* Temporary variables don't need ctor copying */ + if (IS_TMP_VAR != IS_TMP_VAR) { + zval_opt_copy_ctor(&generator->value); + } + } else { + zval *value_ptr = NULL; - /* here we are sure we are dealing with an object */ - do { - if (IS_TMP_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + } else { + ZVAL_MAKE_REF(value_ptr); } + ZVAL_COPY(&generator->value, value_ptr); + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_DUP(&generator->value, value); + } else if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) { + ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } } - } while (0); + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1, free_op2; - zval *property; + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - container = NULL; + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_DUP(&generator->key, key); + } else if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->key, key); + } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { + ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } else { + ZVAL_COPY_VALUE(&generator->key, key); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + } } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); } else { - return ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + generator->send_target = NULL; } -} -static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *str = EX_VAR(opline->result.var); - zval *var; - zval var_copy; - int use_copy = 0; + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ SAVE_OPLINE(); - var = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - - if (IS_TMP_VAR == IS_UNUSED) { - /* Initialize for erealloc in add_string_to_string */ - ZVAL_EMPTY_STRING(str); - } - if (Z_TYPE_P(var) != IS_STRING) { - if (IS_TMP_VAR != IS_TMP_VAR) { - ZVAL_DEREF(var); - } - if (Z_TYPE_P(var) != IS_STRING) { - use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); + ZEND_VM_RETURN(); +} - if (use_copy) { - var = &var_copy; - } - } - } - add_string_to_string(str, str, var); +static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; - if (use_copy) { - zend_string_release(Z_STR_P(var)); - } - /* original comment, possibly problematic: - * FREE_OP is missing intentionally here - we're always working on the same temporary variable - * (Zeev): I don't think it's problematic, we only use variables - * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're - * string offsets or overloaded objects - */ + SAVE_OPLINE(); + pow_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_free_op free_op1, free_op2; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; SAVE_OPLINE(); + fast_mod_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); +static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; - if (IS_TMP_VAR != IS_CONST && - UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Method name must be a string"); - } - - object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); - } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - zval_ptr_dtor_nogc(free_op2); - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); - } - - obj = Z_OBJ_P(object); - called_scope = obj->ce; + SAVE_OPLINE(); + shift_left_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_TMP_VAR != IS_CONST || - EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { - zend_object *orig_obj = obj; +static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; - if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); - } + SAVE_OPLINE(); + shift_right_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_TMP_VAR == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(obj == orig_obj)) { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); - } - } +static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; - } else { - GC_REFCOUNT(obj)++; /* For $this pointer */ - } + SAVE_OPLINE(); + concat_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); +static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + SAVE_OPLINE(); + fast_is_identical_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - + fast_is_not_identical_function(result, + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *expr_ptr, new_expr; + zend_free_op free_op1, free_op2; SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); - } - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + bitwise_or_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } else if (IS_TMP_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) { - expr_ptr = Z_REFVAL_P(expr_ptr); - if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); +static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; - } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } - } + SAVE_OPLINE(); + bitwise_and_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - zend_string *str; - zend_ulong hval; +static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; -add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; - } - zval_ptr_dtor_nogc(free_op2); - } else { - zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); - } + SAVE_OPLINE(); + bitwise_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE + zend_free_op free_op1, free_op2; - array = EX_VAR(opline->result.var); - if (IS_TMP_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_NEW_ARR(array); - zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); + SAVE_OPLINE(); + boolean_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_TMP_VAR != IS_UNUSED) { - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init(Z_ARRVAL_P(array), 0); - } - } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; - if (IS_TMP_VAR == IS_UNUSED) { - ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_TMP_VAR != IS_UNUSED - } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#endif - } + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; zval *container; - int result; - zend_ulong hval; - zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_TMP_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); - zval *value; - zend_string *str; +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zend_free_op free_op1, free_op2; -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } - } -str_index_prop: - value = zend_hash_find_ind(ht, str); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - value = NULL; - break; - } - } + SAVE_OPLINE(); - if (opline->extended_value & ZEND_ISSET) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); - } - } else if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { - result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check element of non-array"); - result = 0; + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + container = NULL; + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ - zval tmp; + zval_ptr_dtor_nogc(free_op2); - result = 0; - if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(offset); - } - if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ - || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ - && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { - ZVAL_DUP(&tmp, offset); - convert_to_long(&tmp); - offset = &tmp; - } - } - if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { - if ((opline->extended_value & ZEND_ISSET) || - Z_STRVAL_P(container)[offset->value.lval] != '0') { - result = 1; - } - } - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + if (IS_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); } - - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container; - int result; - zval *offset; + zend_free_op free_op1; + zval *expr; + zend_bool result; SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; + ce = Z_CE_P(EX_VAR(opline->op2.var)); } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + result = 0; } - - zval_ptr_dtor_nogc(free_op2); ZVAL_BOOL(EX_VAR(opline->result.var), result); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -12467,21 +11293,21 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR } /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { + if (IS_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { + if (IS_VAR == IS_CONST) { ZVAL_DUP(&generator->key, key); - } else if (IS_TMP_VAR == IS_TMP_VAR) { + } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { + } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - + zval_ptr_dtor_nogc(free_op2); } else { ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { + if (IS_VAR == IS_CV) { if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); } } @@ -12517,7 +11343,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -12525,347 +11351,485 @@ static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); pow_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zval *container; + zend_free_op free_op1; SAVE_OPLINE(); - fast_mod_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} -static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + container = NULL; + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } - SAVE_OPLINE(); - shift_left_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + + } else { + if (IS_UNUSED == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op1); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; + zval *expr_ptr, new_expr; SAVE_OPLINE(); - shift_right_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = NULL; + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + } + ZVAL_MAKE_REF(expr_ptr); + Z_ADDREF_P(expr_ptr); + + } else { + expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } else if (IS_TMP_VAR == IS_CONST) { + if (!Z_IMMUTABLE_P(expr_ptr)) { + ZVAL_DUP(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } + } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) { + expr_ptr = Z_REFVAL_P(expr_ptr); + if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); + + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + + if (IS_UNUSED != IS_UNUSED) { + + zval *offset = NULL; + zend_string *str; + zend_ulong hval; + +add_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_UNUSED != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index; + case IS_FALSE: + hval = 0; + goto num_index; + case IS_TRUE: + hval = 1; + goto num_index; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto add_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); + /* do nothing */ + break; + } + + } else { + zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zval *array; + uint32_t size; USE_OPLINE - zend_free_op free_op1, free_op2; + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + } else { + size = 0; + } + ZVAL_NEW_ARR(array); + zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); + + if (IS_TMP_VAR != IS_UNUSED) { + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init(Z_ARRVAL_P(array), 0); + } + } + + if (IS_TMP_VAR == IS_UNUSED) { + ZEND_VM_NEXT_OPCODE(); +#if 0 || IS_TMP_VAR != IS_UNUSED + } else { + return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +#endif + } +} + +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in EX(return_value) */ + zend_generator *generator = (zend_generator *) EX(return_value); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + ZVAL_COPY_VALUE(&generator->value, value); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + + /* Temporary variables don't need ctor copying */ + if (IS_TMP_VAR != IS_TMP_VAR) { + zval_opt_copy_ctor(&generator->value); + } + } else { + zval *value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + } else { + ZVAL_MAKE_REF(value_ptr); + } + ZVAL_COPY(&generator->value, value_ptr); + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_DUP(&generator->value, value); + } else if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) { + ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST) { + ZVAL_DUP(&generator->key, key); + } else if (IS_UNUSED == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->key, key); + } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { + ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + + } else { + ZVAL_COPY_VALUE(&generator->key, key); + if (IS_UNUSED == IS_CV) { + if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + } + } + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ SAVE_OPLINE(); - concat_function(EX_VAR(opline->result.var), + + ZEND_VM_RETURN(); +} + +static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + + SAVE_OPLINE(); + fast_mod_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); - fast_is_identical_function(EX_VAR(opline->result.var), + shift_left_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *result = EX_VAR(opline->result.var); + zend_free_op free_op1; SAVE_OPLINE(); - fast_is_not_identical_function(result, + shift_right_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); - bitwise_or_function(EX_VAR(opline->result.var), + concat_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); - bitwise_and_function(EX_VAR(opline->result.var), + fast_is_identical_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - bitwise_xor_function(EX_VAR(opline->result.var), + fast_is_not_identical_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); - boolean_xor_function(EX_VAR(opline->result.var), + bitwise_or_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *varname; - zval *retval; - zend_string *name; - HashTable *target_symbol_table; SAVE_OPLINE(); - varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - if (IS_TMP_VAR == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - zend_string_addref(name); - } else { - name = zval_get_string(varname); - } - - if (IS_VAR != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - if (IS_TMP_VAR != IS_CONST) { - zend_string_release(name); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - retval = zend_std_get_static_property(ce, name, 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - retval = zend_hash_find(target_symbol_table, name); - if (retval == NULL) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1 TSRMLS_CC); - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - zval_ptr_dtor_nogc(free_op1); - } - } - - if (IS_TMP_VAR != IS_CONST) { - zend_string_release(name); - } + bitwise_and_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { - ZVAL_UNREF(retval); - } - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + USE_OPLINE + zend_free_op free_op1; -static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + SAVE_OPLINE(); + bitwise_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); -static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op1; - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + SAVE_OPLINE(); + boolean_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); -static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); @@ -12878,36 +11842,36 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - zval_ptr_dtor_nogc(free_op2); + } else { - if (IS_VAR == IS_UNUSED) { + if (IS_CV == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *container; - zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -12918,7 +11882,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAND /* here we are sure we are dealing with an object */ do { - if (IS_VAR == IS_CONST && + if (IS_CV == IS_CONST && EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); zend_object *zobj = Z_OBJ_P(container); @@ -12938,7 +11902,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAND } } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); if (retval != EX_VAR(opline->result.var)) { ZVAL_COPY(EX_VAR(opline->result.var), retval); @@ -12946,23 +11910,22 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAND } while (0); } - zval_ptr_dtor_nogc(free_op2); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *container; - zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -12972,7 +11935,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN /* here we are sure we are dealing with an object */ do { - if (IS_VAR == IS_CONST && + if (IS_CV == IS_CONST && EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); zend_object *zobj = Z_OBJ_P(container); @@ -12992,7 +11955,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN } } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); if (retval != EX_VAR(opline->result.var)) { ZVAL_COPY(EX_VAR(opline->result.var), retval); @@ -13000,24 +11963,23 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN } while (0); } - zval_ptr_dtor_nogc(free_op2); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *property; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = NULL; if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { @@ -13026,8 +11988,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -13035,21 +11997,21 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval *str = EX_VAR(opline->result.var); zval *var; zval var_copy; int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_TMP_VAR == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -13057,15 +12019,10 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ } if (Z_TYPE_P(var) != IS_STRING) { - if (IS_VAR != IS_TMP_VAR) { - ZVAL_DEREF(var); - } - if (Z_TYPE_P(var) != IS_STRING) { - use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); + use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); - if (use_copy) { - var = &var_copy; - } + if (use_copy) { + var = &var_copy; } } add_string_to_string(str, str, var); @@ -13079,17 +12036,16 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're * string offsets or overloaded objects */ - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -13097,9 +12053,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE SAVE_OPLINE(); - function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (IS_VAR != IS_CONST && + if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -13113,12 +12069,12 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - zval_ptr_dtor_nogc(free_op2); + if (EG(exception) != NULL) { HANDLE_EXCEPTION(); @@ -13156,7 +12112,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE obj = Z_OBJ_P(object); called_scope = obj->ce; - if (IS_VAR != IS_CONST || + if (IS_CV != IS_CONST || EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; @@ -13165,11 +12121,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE } /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } - if (IS_VAR == IS_CONST && + if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && EXPECTED(obj == orig_obj)) { @@ -13186,29 +12142,12 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -13243,9 +12182,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD } } - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if (IS_CV != IS_UNUSED) { + + zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zend_string *str; zend_ulong hval; @@ -13261,7 +12200,7 @@ num_index: break; case IS_STRING: str = Z_STR_P(offset); - if (IS_VAR != IS_CONST) { + if (IS_CV != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index; } @@ -13288,7 +12227,7 @@ str_index: /* do nothing */ break; } - zval_ptr_dtor_nogc(free_op2); + } else { zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } @@ -13296,7 +12235,7 @@ str_index: ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -13322,162 +12261,15 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); #if 0 || IS_TMP_VAR != IS_UNUSED } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #endif } } -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval tmp, *varname; - HashTable *target_symbol_table; zend_free_op free_op1; - - SAVE_OPLINE(); - if (IS_TMP_VAR == IS_CV && - IS_VAR == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - zval *var = EX_VAR(opline->op1.var); - - if (Z_REFCOUNTED_P(var)) { - zend_refcounted *garbage = Z_COUNTED_P(var); - - if (!--GC_REFCOUNT(garbage)) { - ZVAL_UNDEF(var); - _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); - } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); - } - } else { - ZVAL_UNDEF(var); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_VAR != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_TMP_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_TMP_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - - SAVE_OPLINE(); - if (IS_TMP_VAR == IS_CV && - IS_VAR == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - value = EX_VAR(opline->op1.var); - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !i_zend_is_true(value TSRMLS_CC)); - CHECK_EXCEPTION(); - } - ZEND_VM_NEXT_OPCODE(); - } else { - zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_VAR != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_TMP_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - value && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !value || !i_zend_is_true(value TSRMLS_CC)); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; int result; zend_ulong hval; @@ -13485,7 +12277,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_O SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_TMP_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); @@ -13495,7 +12287,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_O isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_VAR != IS_CONST) { + if (IS_CV != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index_prop; } @@ -13555,7 +12347,7 @@ num_index_prop: result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + if (IS_CV & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -13581,28 +12373,27 @@ num_index_prop: result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_ptr_dtor_nogc(free_op2); ZVAL_BOOL(EX_VAR(opline->result.var), result); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; int result; zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); result = 0; @@ -13614,53 +12405,13 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_ result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *expr; - zend_bool result; - - SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; - - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); - } else { - result = 0; - } ZVAL_BOOL(EX_VAR(opline->result.var), result); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -13741,21 +12492,21 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR } /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { + if (IS_CV == IS_CONST) { ZVAL_DUP(&generator->key, key); - } else if (IS_VAR == IS_TMP_VAR) { + } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { + } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) { ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); + } else { ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { + if (IS_CV == IS_CV) { if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); } } @@ -13791,251 +12542,357 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); pow_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *varname; - zval *retval; - zend_string *name; - HashTable *target_symbol_table; + zval *container; + zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); - varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_TMP_VAR == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - zend_string_addref(name); + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + ZVAL_NULL(EX_VAR(opline->result.var)); } else { - name = zval_get_string(varname); - } + zval *retval; - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; + /* here we are sure we are dealing with an object */ + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - if (IS_TMP_VAR != IS_CONST) { - zend_string_release(name); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - retval = zend_std_get_static_property(ce, name, 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - retval = zend_hash_find(target_symbol_table, name); - if (retval == NULL) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); break; - EMPTY_SWITCH_DEFAULT_CASE() + } } } - } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1 TSRMLS_CC); - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - zval_ptr_dtor_nogc(free_op1); - } - } - if (IS_TMP_VAR != IS_CONST) { - zend_string_release(name); - } + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { - ZVAL_UNREF(retval); - } - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } while (0); } + + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + USE_OPLINE + zend_free_op free_op1; + zval *container; + zend_free_op free_op2; + zval *offset; -static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); -static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; -static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + /* here we are sure we are dealing with an object */ + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } + } -static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); -static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } while (0); + } + + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; - zend_free_op free_op1; - - SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + /* Behave like FETCH_OBJ_W */ + zend_free_op free_op1, free_op2; + zval *property; + + SAVE_OPLINE(); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + container = NULL; + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - container = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } else { - if (IS_UNUSED == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op1); + return ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *expr_ptr, new_expr; + zend_free_op free_op2; + zval *str = EX_VAR(opline->result.var); + zval *var; + zval var_copy; + int use_copy = 0; SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); - } - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } else if (IS_TMP_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) { - expr_ptr = Z_REFVAL_P(expr_ptr); - if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); + if (IS_TMP_VAR == IS_UNUSED) { + /* Initialize for erealloc in add_string_to_string */ + ZVAL_EMPTY_STRING(str); + } - } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); + if (Z_TYPE_P(var) != IS_STRING) { + use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); + + if (use_copy) { + var = &var_copy; } } + add_string_to_string(str, str, var); - if (IS_UNUSED != IS_UNUSED) { + if (use_copy) { + zend_string_release(Z_STR_P(var)); + } + /* original comment, possibly problematic: + * FREE_OP is missing intentionally here - we're always working on the same temporary variable + * (Zeev): I don't think it's problematic, we only use variables + * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're + * string offsets or overloaded objects + */ + zval_ptr_dtor_nogc(free_op2); - zval *offset = NULL; - zend_string *str; - zend_ulong hval; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} -add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_free_op free_op1, free_op2; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + + SAVE_OPLINE(); + + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Method name must be a string"); + } + + object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + + if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); + } + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zval_ptr_dtor_nogc(free_op2); + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); + } + + obj = Z_OBJ_P(object); + called_scope = obj->ce; + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST || + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { + zend_object *orig_obj = obj; + + if (UNEXPECTED(obj->handlers->get_method == NULL)) { + zend_error_noreturn(E_ERROR, "Object does not support method calls"); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); + } + } + + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + obj = NULL; + } else { + GC_REFCOUNT(obj)++; /* For $this pointer */ + } + + EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op2); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = NULL; + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + } + ZVAL_MAKE_REF(expr_ptr); + Z_ADDREF_P(expr_ptr); + + } else { + expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } else if (IS_TMP_VAR == IS_CONST) { + if (!Z_IMMUTABLE_P(expr_ptr)) { + ZVAL_DUP(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } + } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) { + expr_ptr = Z_REFVAL_P(expr_ptr); + if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); + + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zend_free_op free_op2; + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zend_string *str; + zend_ulong hval; + +add_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; case IS_LONG: hval = Z_LVAL_P(offset); num_index: @@ -14043,7 +12900,7 @@ num_index: break; case IS_STRING: str = Z_STR_P(offset); - if (IS_UNUSED != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index; } @@ -14070,7 +12927,7 @@ str_index: /* do nothing */ break; } - + zval_ptr_dtor_nogc(free_op2); } else { zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } @@ -14078,7 +12935,7 @@ str_index: ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -14104,5434 +12961,1871 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); #if 0 || IS_TMP_VAR != IS_UNUSED } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #endif } } -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval tmp, *varname; - HashTable *target_symbol_table; - zend_free_op free_op1; + zend_free_op free_op1, free_op2; + zval *container; + int result; + zend_ulong hval; + zval *offset; SAVE_OPLINE(); - if (IS_TMP_VAR == IS_CV && - IS_UNUSED == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - zval *var = EX_VAR(opline->op1.var); - - if (Z_REFCOUNTED_P(var)) { - zend_refcounted *garbage = Z_COUNTED_P(var); - - if (!--GC_REFCOUNT(garbage)) { - ZVAL_UNDEF(var); - _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); - } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); - } - } else { - ZVAL_UNDEF(var); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; + if (IS_TMP_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value; + zend_string *str; - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_TMP_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); } +str_index_prop: + value = zend_hash_find_ind(ht, str); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 1; + goto num_index_prop; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto isset_again; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + value = NULL; + break; + } } - zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_TMP_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - SAVE_OPLINE(); - if (IS_TMP_VAR == IS_CV && - IS_UNUSED == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - value = EX_VAR(opline->op1.var); if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !i_zend_is_true(value TSRMLS_CC)); - CHECK_EXCEPTION(); - } - ZEND_VM_NEXT_OPCODE(); - } else { - zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { - HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_TMP_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); + zend_error(E_NOTICE, "Trying to check element of non-array"); + result = 0; } - zval_ptr_dtor_nogc(free_op1); - - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - value && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !value || !i_zend_is_true(value TSRMLS_CC)); + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; } + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ + zval tmp; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } -} - -static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - /* The generator object is stored in EX(return_value) */ - zend_generator *generator = (zend_generator *) EX(return_value); - - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); - } - } else { - zval *value_ptr = NULL; - - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); - } - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - } else { - ZVAL_MAKE_REF(value_ptr); - } - ZVAL_COPY(&generator->value, value_ptr); - + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) { + ZVAL_DEREF(offset); } - } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ + || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ + && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { + ZVAL_DUP(&tmp, offset); + convert_to_long(&tmp); + offset = &tmp; + } + } + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { + if ((opline->extended_value & ZEND_ISSET) || + Z_STRVAL_P(container)[offset->value.lval] != '0') { + result = 1; } } } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); + result = ((opline->extended_value & ZEND_ISSET) == 0); } - /* Set the new yielded key */ - if (IS_UNUSED != IS_UNUSED) { + zval_ptr_dtor_nogc(free_op2); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - zval *key = NULL; +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; + int result; + zval *offset; - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->key, key); - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; } } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; + result = ((opline->extended_value & ZEND_ISSET) == 0); } - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); + zval_ptr_dtor_nogc(free_op2); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; SAVE_OPLINE(); - fast_mod_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + bitwise_not_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; SAVE_OPLINE(); - shift_left_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + boolean_not_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; + zval *var_ptr; SAVE_OPLINE(); - shift_right_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } -static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_increment_function(var_ptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } - SAVE_OPLINE(); - concat_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + increment_function(var_ptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; + zval *var_ptr; SAVE_OPLINE(); - fast_is_identical_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_decrement_function(var_ptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + decrement_function(var_ptr); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *result = EX_VAR(opline->result.var); + zval *var_ptr; SAVE_OPLINE(); - fast_is_not_identical_function(result, - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + fast_increment_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + ZVAL_DEREF(var_ptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_opt_copy_ctor(var_ptr); + increment_function(var_ptr); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; + zval *var_ptr; SAVE_OPLINE(); - bitwise_or_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + fast_decrement_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + ZVAL_DEREF(var_ptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_opt_copy_ctor(var_ptr); + + decrement_function(var_ptr); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; + zval *z; SAVE_OPLINE(); - bitwise_and_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + z = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + + zend_print_variable(z TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRINT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - SAVE_OPLINE(); - bitwise_xor_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + ZVAL_LONG(EX_VAR(opline->result.var), 1); + return ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMPZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; + zval *val; SAVE_OPLINE(); - boolean_xor_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (IS_VAR == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } + } + + if (i_zend_is_true(val TSRMLS_CC)) { + opline++; + } else { + opline = opline->op2.jmp_addr; + } + zval_ptr_dtor_nogc(free_op1); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *container; + zval *val; SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } + } + if (i_zend_is_true(val TSRMLS_CC)) { + opline = opline->op2.jmp_addr; + } else { + opline++; + } zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *container; + zval *val; SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_TMP_VAR) { + if (EXPECTED(Z_TYPE_P(val) == IS_TRUE)) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } + } + if (i_zend_is_true(val TSRMLS_CC)) { + opline = (zend_op*)(((char*)opline) + opline->extended_value); + } else { + opline = opline->op2.jmp_addr; + } zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zend_free_op free_op1; + zval *val; SAVE_OPLINE(); + val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - container = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + if (IS_VAR == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); } + } - + if (i_zend_is_true(val TSRMLS_CC)) { + zval_ptr_dtor_nogc(free_op1); + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline++; } else { - if (IS_CV == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline = opline->op2.jmp_addr; } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *container; - - zval *offset; + zval *val; SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); + if (IS_VAR == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } + } + if (i_zend_is_true(val TSRMLS_CC)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline = opline->op2.jmp_addr; } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline++; } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *retval_ptr; zend_free_op free_op1; - zval *container; - - zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - ZVAL_NULL(EX_VAR(opline->result.var)); + if (!EX(return_value)) { + zval_ptr_dtor_nogc(free_op1); } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { + zval_copy_ctor_func(EX(return_value)); } } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(retval_ptr)) { + ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr)); + zval_ptr_dtor_nogc(free_op1); + } else { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } - } while (0); + } } - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; + zval *retval_ptr; + zend_free_op free_op1; - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1; - zval *property; + SAVE_OPLINE(); - SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - container = NULL; + do { + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR || + (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { + /* Not supposed to happen, but we'll allow it */ + zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + if (!EX(return_value)) { + if (IS_VAR == IS_TMP_VAR) { + zval_ptr_dtor_nogc(free_op1); + } + } else { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + if (IS_VAR != IS_TMP_VAR) { + zval_opt_copy_ctor_no_imm(EX(return_value)); + } + } + break; } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } else { - return ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + if (IS_VAR == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (EX(return_value)) { + ZVAL_NEW_REF(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + } + break; + } + } + + if (EX(return_value)) { + ZVAL_MAKE_REF(retval_ptr); + Z_ADDREF_P(retval_ptr); + ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + } + } while (0); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *str = EX_VAR(opline->result.var); - zval *var; - zval var_copy; - int use_copy = 0; + zval *value; + zend_free_op free_op1; SAVE_OPLINE(); - var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + value = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - if (IS_TMP_VAR == IS_UNUSED) { - /* Initialize for erealloc in add_string_to_string */ - ZVAL_EMPTY_STRING(str); + if (IS_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Can only throw objects"); } - if (Z_TYPE_P(var) != IS_STRING) { - if (IS_CV != IS_TMP_VAR) { - ZVAL_DEREF(var); - } - if (Z_TYPE_P(var) != IS_STRING) { - use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); - - if (use_copy) { - var = &var_copy; - } - } + zend_exception_save(TSRMLS_C); + if (IS_VAR != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value); } - add_string_to_string(str, str, var); - if (use_copy) { - zend_string_release(Z_STR_P(var)); - } - /* original comment, possibly problematic: - * FREE_OP is missing intentionally here - we're always working on the same temporary variable - * (Zeev): I don't think it's problematic, we only use variables - * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're - * string offsets or overloaded objects - */ + zend_throw_exception_object(value TSRMLS_CC); + zend_exception_restore(TSRMLS_C); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); +} - CHECK_EXCEPTION(); +static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + zend_free_op free_op1; + + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + arg = ZEND_CALL_ARG(EX(call), opline->op2.num); + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + if (Z_ISREF_P(varptr)) { + ZVAL_COPY(arg, Z_REFVAL_P(varptr)); + zval_ptr_dtor_nogc(free_op1); + } else { + ZVAL_COPY_VALUE(arg, varptr); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg); + } + } ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_free_op free_op1; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; + zval *varptr, *arg; SAVE_OPLINE(); - function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - - if (IS_CV != IS_CONST && - UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) { + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { + return ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); } - object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if (UNEXPECTED(EG(exception) != NULL)) { + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || + (Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) && + (Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) { - HANDLE_EXCEPTION(); + ZVAL_MAKE_REF(varptr); + if (IS_VAR == IS_CV) { + Z_ADDREF_P(varptr); } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); + } else { + if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? + !(opline->extended_value & ZEND_ARG_SEND_SILENT) : + !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { + zend_error(E_STRICT, "Only variables should be passed by reference"); } + } - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } + arg = ZEND_CALL_ARG(EX(call), opline->op2.num); + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + ZVAL_COPY_VALUE(arg, varptr); - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - obj = Z_OBJ_P(object); - called_scope = obj->ce; +static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *varptr, *arg; - if (IS_CV != IS_CONST || - EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { - zend_object *orig_obj = obj; + SAVE_OPLINE(); + varptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); - } + if (IS_VAR == IS_VAR && UNEXPECTED(varptr == NULL)) { + zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); + } - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(obj == orig_obj)) { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); - } + arg = ZEND_CALL_ARG(EX(call), opline->op2.num); + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + if (IS_VAR == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) { + ZVAL_NEW_REF(arg, &EG(uninitialized_zval)); + ZEND_VM_NEXT_OPCODE(); } - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + } else if (IS_VAR == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { + ZVAL_NEW_REF(arg, varptr); } else { - GC_REFCOUNT(obj)++; /* For $this pointer */ + ZVAL_NEW_REF(arg, varptr); + Z_ADDREF_P(arg); + ZVAL_REF(varptr, Z_REF_P(arg)); } - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - - - CHECK_EXCEPTION(); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *varptr, *arg; zend_free_op free_op1; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - CHECK_EXCEPTION(); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { + return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + arg = ZEND_CALL_ARG(EX(call), opline->op2.num); + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + if (Z_ISREF_P(varptr)) { + ZVAL_COPY(arg, Z_REFVAL_P(varptr)); + zval_ptr_dtor_nogc(free_op1); + } else { + ZVAL_COPY_VALUE(arg, varptr); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg); + } + } ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *arg, *param, tmp; zend_free_op free_op1; - zval *expr_ptr, new_expr; - - SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); - } - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); - } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } else if (IS_TMP_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) { - expr_ptr = Z_REFVAL_P(expr_ptr); - if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); + arg = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + param = ZEND_CALL_ARG(EX(call), opline->op2.num); - } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } - } + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { + // TODO: Scalar values don't have reference counters anymore. + // They are assumed to be 1, and they may be easily passed by + // reference now. However, previously scalars with refcount==1 + // might be passed and with refcount>1 might not. We can support + // only single behavior ??? +#if 0 + if (Z_REFCOUNTED_P(arg) && + // This solution breaks the following test (omit warning message) ??? + // Zend/tests/bug61273.phpt + // ext/reflection/tests/bug42976.phpt + // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt +#else + if (!Z_REFCOUNTED_P(arg) || + // This solution breaks the following test (emit warning message) ??? + // ext/pdo_sqlite/tests/pdo_005.phpt +#endif + (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) { - if (IS_CV != IS_UNUSED) { + if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_string *str; - zend_ulong hval; + zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", + opline->op2.num, + EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "", + EX(call)->func->common.scope ? "::" : "", + EX(call)->func->common.function_name->val); -add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { + OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; - } + if (Z_OBJ(EX(call)->This)) { + OBJ_RELEASE(Z_OBJ(EX(call)->This)); + } + EX(call)->func = (zend_function*)&zend_pass_function; + EX(call)->called_scope = NULL; + Z_OBJ(EX(call)->This) = NULL; + + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + if (Z_REFCOUNTED_P(arg)) { + Z_DELREF_P(arg); + } + ZVAL_DUP(&tmp, arg); + ZVAL_NEW_REF(arg, &tmp); + Z_ADDREF_P(arg); + } else if (!Z_ISREF_P(arg)) { + ZVAL_NEW_REF(arg, arg); + Z_ADDREF_P(arg); + } else if (Z_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + ZVAL_COPY_VALUE(param, arg); + } else if (Z_ISREF_P(arg) && + /* don't separate references for __call */ + (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { + ZVAL_DUP(param, Z_REFVAL_P(arg)); } else { - zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); + ZVAL_COPY(param, arg); } + + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE + zval object_zval; + zend_function *constructor; + zend_class_entry *ce; - array = EX_VAR(opline->result.var); - if (IS_TMP_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + SAVE_OPLINE(); + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); + } } else { - size = 0; + ce = Z_CE_P(EX_VAR(opline->op1.var)); } - ZVAL_NEW_ARR(array); - zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); - - if (IS_TMP_VAR != IS_UNUSED) { - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init(Z_ARRVAL_P(array), 0); + if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { + if (ce->ce_flags & ZEND_ACC_INTERFACE) { + zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val); + } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { + zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val); + } else { + zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); } } + object_init_ex(&object_zval, ce); + constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC); - if (IS_TMP_VAR == IS_UNUSED) { - ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_TMP_VAR != IS_UNUSED + if (constructor == NULL) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); + } else { + OBJ_RELEASE(Z_OBJ(object_zval)); + } + ZEND_VM_JMP(opline->op2.jmp_addr); } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#endif + /* We are not handling overloaded classes right now */ + EX(call) = zend_vm_stack_push_call_frame( + ZEND_CALL_FUNCTION | ZEND_CALL_CTOR | + (RETURN_VALUE_USED(opline) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED), + constructor, + opline->extended_value, + ce, + Z_OBJ(object_zval), + EX(call) TSRMLS_CC); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); + EX(call)->return_value = EX_VAR(opline->result.var); + } else { + EX(call)->return_value = NULL; + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *container; - int result; - zend_ulong hval; - zval *offset; + zval *obj; + zend_class_entry *ce; + zend_function *clone; + zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - - if (IS_TMP_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); - zval *value; - zend_string *str; + obj = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } - } -str_index_prop: - value = zend_hash_find_ind(ht, str); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - value = NULL; - break; - } + if (IS_VAR == IS_CONST || + (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } + zend_error_noreturn(E_ERROR, "__clone method called on non-object"); + } - if (opline->extended_value & ZEND_ISSET) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); - } - } else if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { - result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + ce = Z_OBJCE_P(obj); + clone = ce ? ce->clone : NULL; + clone_call = Z_OBJ_HT_P(obj)->clone_obj; + if (UNEXPECTED(clone_call == NULL)) { + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); } else { - zend_error(E_NOTICE, "Trying to check element of non-array"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); } - } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ - zval tmp; + } - result = 0; - if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(offset); + if (ce && clone) { + if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { + /* Ensure that if we're calling a private function, we're allowed to do so. + */ + if (UNEXPECTED(ce != EG(scope))) { + zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); } - if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ - || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ - && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { - ZVAL_DUP(&tmp, offset); - convert_to_long(&tmp); - offset = &tmp; + } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { + /* Ensure that if we're calling a protected function, we're allowed to do so. + */ + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { + zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); } } - if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { - if ((opline->extended_value & ZEND_ISSET) || - Z_STRVAL_P(container)[offset->value.lval] != '0') { - result = 1; - } - } - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); } - ZVAL_BOOL(EX_VAR(opline->result.var), result); + if (EXPECTED(EG(exception) == NULL)) { + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj TSRMLS_CC)); + if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var))); + } + } zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *container; - int result; - zval *offset; + zval *expr; + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + switch (opline->extended_value) { + case IS_NULL: + /* This code is taken from convert_to_null. However, it does not seems very useful, + * because a conversion to null always results in the same value. This could only + * be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */ +#if 0 + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + ZVAL_DEREF(expr); + } + if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) { + if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL TSRMLS_CC) == SUCCESS) { + break; + } + } +#endif + + ZVAL_NULL(result); + break; + case _IS_BOOL: + ZVAL_BOOL(result, zend_is_true(expr TSRMLS_CC)); + break; + case IS_LONG: + ZVAL_LONG(result, zval_get_long(expr)); + break; + case IS_DOUBLE: + ZVAL_DOUBLE(result, zval_get_double(expr)); + break; + case IS_STRING: + ZVAL_STR(result, zval_get_string(expr)); + break; + default: + /* If value is already of correct type, return it directly */ + if (Z_TYPE_P(expr) == opline->extended_value) { + ZVAL_COPY_VALUE(result, expr); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) { + zval_copy_ctor_func(result); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + if (opline->extended_value == IS_ARRAY) { + if (Z_TYPE_P(expr) != IS_OBJECT) { + ZVAL_NEW_ARR(result); + zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0); + if (Z_TYPE_P(expr) != IS_NULL) { + expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { + zval_copy_ctor_func(expr); + } + } else { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + } + } else { + ZVAL_COPY_VALUE(result, expr); + Z_ADDREF_P(result); + convert_to_array(result); + } + } else { + if (Z_TYPE_P(expr) != IS_ARRAY) { + object_init(result); + if (Z_TYPE_P(expr) != IS_NULL) { + expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { + zval_copy_ctor_func(expr); + } + } else { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + } + } else { + ZVAL_COPY_VALUE(result, expr); + zval_opt_copy_ctor(result); + convert_to_object(result); + } + } } - ZVAL_BOOL(EX_VAR(opline->result.var), result); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op1; + zval *array_ptr, *array_ref, iterator, tmp; + HashTable *fe_ht; + zend_object_iterator *iter = NULL; + zend_class_entry *ce = NULL; + zend_bool is_empty = 0; - /* The generator object is stored in EX(return_value) */ - zend_generator *generator = (zend_generator *) EX(return_value); - - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); - } - } else { - zval *value_ptr = NULL; + SAVE_OPLINE(); - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && + (opline->extended_value & ZEND_FE_FETCH_BYREF)) { + array_ptr = array_ref = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + ZVAL_DEREF(array_ptr); + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + SEPARATE_ARRAY(array_ptr); + if (!Z_ISREF_P(array_ref)) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); + } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { + ce = Z_OBJCE_P(array_ptr); + if (ce->get_iterator == NULL) { + Z_ADDREF_P(array_ptr); + } + array_ref = array_ptr; + } else { + if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); + } + } else { + array_ptr = array_ref = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + ZVAL_DEREF(array_ptr); + if (IS_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&tmp, array_ptr); + if (Z_OPT_IMMUTABLE_P(&tmp)) { + zval_copy_ctor_func(&tmp); + } + array_ref = array_ptr = &tmp; + if (Z_TYPE_P(array_ptr) == IS_OBJECT) { + ce = Z_OBJCE_P(array_ptr); + if (ce && ce->get_iterator) { + Z_DELREF_P(array_ref); } - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - } else { - ZVAL_MAKE_REF(value_ptr); + } + } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { + ce = Z_OBJCE_P(array_ptr); + if (!ce->get_iterator) { + if (IS_VAR == IS_CV) { + Z_ADDREF_P(array_ref); } - ZVAL_COPY(&generator->value, value_ptr); - } - } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - + } else if (Z_IMMUTABLE_P(array_ref)) { + if (IS_VAR == IS_CV) { + zval_copy_ctor_func(array_ref); + Z_ADDREF_P(array_ref); } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + ZVAL_COPY_VALUE(&tmp, array_ref); + zval_copy_ctor_func(&tmp); + array_ptr = array_ref = &tmp; + } + } else if (Z_REFCOUNTED_P(array_ref)) { + if (IS_VAR == IS_CONST || + (IS_VAR == IS_CV && + !Z_ISREF_P(array_ref) && + Z_REFCOUNT_P(array_ref) > 1) || + (IS_VAR == IS_VAR && + !Z_ISREF_P(array_ref) && + Z_REFCOUNT_P(array_ref) > 2)) { + if (IS_VAR == IS_VAR) { + Z_DELREF_P(array_ref); + } + ZVAL_DUP(&tmp, array_ref); + array_ptr = array_ref = &tmp; + } else if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) { + ZVAL_UNREF(array_ref); + array_ptr = array_ref; + } + if (Z_IMMUTABLE_P(array_ptr)) { + zval_copy_ctor_func(array_ptr); + } else if (Z_ISREF_P(array_ref) && + Z_COPYABLE_P(array_ptr) && + Z_REFCOUNT_P(array_ptr) > 1) { + Z_DELREF_P(array_ptr); + zval_copy_ctor_func(array_ptr); + } + if (IS_VAR == IS_CV) { + Z_ADDREF_P(array_ref); } } } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); } - /* Set the new yielded key */ - if (IS_CV != IS_UNUSED) { - - zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->key, key); - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + if (ce && ce->get_iterator) { + iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF TSRMLS_CC); + if (IS_VAR == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) { + zval_ptr_dtor_nogc(free_op1); + } + if (iter && EXPECTED(EG(exception) == NULL)) { + ZVAL_OBJ(&iterator, &iter->std); + array_ptr = array_ref = &iterator; } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name->val); + } + zend_throw_exception_internal(NULL TSRMLS_CC); + HANDLE_EXCEPTION(); } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; } - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - -static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - pow_function(EX_VAR(opline->result.var), - _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - bitwise_not_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - boolean_not_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *var_ptr; - - SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } + if (iter) { + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array_ref); + if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } + HANDLE_EXCEPTION(); + } + } + is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS; + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array_ref); + if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ + } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { + HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var); + HashPosition pos = 0; + Bucket *p; - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - fast_increment_function(var_ptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + while (1) { + if (pos >= fe_ht->nNumUsed) { + is_empty = 1; + if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } + ZEND_VM_JMP(opline->op2.jmp_addr); + } + p = fe_ht->arData + pos; + if (Z_TYPE(p->val) == IS_UNDEF || + (Z_TYPE(p->val) == IS_INDIRECT && + Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) { + pos++; + continue; + } + if (!ce || + !p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key TSRMLS_CC) == SUCCESS) { + break; + } + pos++; } - ZEND_VM_NEXT_OPCODE(); + fe_ht->nInternalPointer = pos; + ptr->pos = pos; + ptr->ht = fe_ht; + ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; + is_empty = 0; + } else { + zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + is_empty = 1; } - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } + if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } + if (is_empty) { + ZEND_VM_JMP(opline->op2.jmp_addr); + } else { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - increment_function(var_ptr); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *var_ptr; - SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - fast_decrement_function(var_ptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - } - ZEND_VM_NEXT_OPCODE(); - } + zval *array, *array_ref; + zval *value; + HashTable *fe_ht; + HashPointer *ptr; + HashPosition pos; + Bucket *p; - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); + array = array_ref = EX_VAR(opline->op1.var); + if (Z_ISREF_P(array)) { + array = Z_REFVAL_P(array); + // TODO: referenced value might be changed to different array ??? + if (Z_IMMUTABLE_P(array)) { + zval_copy_ctor_func(array); } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - decrement_function(var_ptr); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } + SAVE_OPLINE(); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *var_ptr; - - SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - fast_increment_function(var_ptr); - ZEND_VM_NEXT_OPCODE(); - } - - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - ZVAL_DEREF(var_ptr); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - zval_opt_copy_ctor(var_ptr); - - increment_function(var_ptr); - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *var_ptr; - - SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - fast_decrement_function(var_ptr); - ZEND_VM_NEXT_OPCODE(); - } - - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - ZVAL_DEREF(var_ptr); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - zval_opt_copy_ctor(var_ptr); - - decrement_function(var_ptr); - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *z; - - SAVE_OPLINE(); - z = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - zend_print_variable(z TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_PRINT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - ZVAL_LONG(EX_VAR(opline->result.var), 1); - return ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_JMPZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *val; - - SAVE_OPLINE(); - val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } - } - - if (i_zend_is_true(val TSRMLS_CC)) { - opline++; - } else { - opline = opline->op2.jmp_addr; - } - zval_ptr_dtor_nogc(free_op1); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline); -} - -static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *val; - - SAVE_OPLINE(); - val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); - } - } - - if (i_zend_is_true(val TSRMLS_CC)) { - opline = opline->op2.jmp_addr; - } else { - opline++; - } - zval_ptr_dtor_nogc(free_op1); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline); -} - -static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *val; - - SAVE_OPLINE(); - val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_TMP_VAR) { - if (EXPECTED(Z_TYPE_P(val) == IS_TRUE)) { - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } - } - - if (i_zend_is_true(val TSRMLS_CC)) { - opline = (zend_op*)(((char*)opline) + opline->extended_value); - } else { - opline = opline->op2.jmp_addr; - } - zval_ptr_dtor_nogc(free_op1); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline); -} - -static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *val; - - SAVE_OPLINE(); - val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } - } - - if (i_zend_is_true(val TSRMLS_CC)) { - zval_ptr_dtor_nogc(free_op1); - ZVAL_TRUE(EX_VAR(opline->result.var)); - opline++; - } else { - zval_ptr_dtor_nogc(free_op1); - ZVAL_FALSE(EX_VAR(opline->result.var)); - opline = opline->op2.jmp_addr; - } - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline); -} - -static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *val; - - SAVE_OPLINE(); - val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); - } - } - if (i_zend_is_true(val TSRMLS_CC)) { - ZVAL_TRUE(EX_VAR(opline->result.var)); - opline = opline->op2.jmp_addr; - } else { - ZVAL_FALSE(EX_VAR(opline->result.var)); - opline++; - } - zval_ptr_dtor_nogc(free_op1); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline); -} - -static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *retval_ptr; - zend_free_op free_op1; - - SAVE_OPLINE(); - retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (!EX(return_value)) { - zval_ptr_dtor_nogc(free_op1); - } else { - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { - zval_copy_ctor_func(EX(return_value)); - } - } - } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(retval_ptr)) { - ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr)); - zval_ptr_dtor_nogc(free_op1); - } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); - } - } - } - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *retval_ptr; - zend_free_op free_op1; - - SAVE_OPLINE(); - - do { - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR || - (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { - /* Not supposed to happen, but we'll allow it */ - zend_error(E_NOTICE, "Only variable references should be returned by reference"); - - retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - if (!EX(return_value)) { - if (IS_VAR == IS_TMP_VAR) { - zval_ptr_dtor_nogc(free_op1); - } - } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (IS_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor_no_imm(EX(return_value)); - } - } - break; - } - - retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); - } - - if (IS_VAR == IS_VAR) { - if (retval_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { - zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); - } - break; - } - } - - if (EX(return_value)) { - ZVAL_MAKE_REF(retval_ptr); - Z_ADDREF_P(retval_ptr); - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - } - } while (0); - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zend_free_op free_op1; - - SAVE_OPLINE(); - value = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Can only throw objects"); - } - - zend_exception_save(TSRMLS_C); - if (IS_VAR != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - - zend_throw_exception_object(value TSRMLS_CC); - zend_exception_restore(TSRMLS_C); - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); -} - -static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - zend_free_op free_op1; - - varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - arg = ZEND_CALL_ARG(EX(call), opline->op2.num); - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(varptr)) { - ZVAL_COPY(arg, Z_REFVAL_P(varptr)); - zval_ptr_dtor_nogc(free_op1); - } else { - ZVAL_COPY_VALUE(arg, varptr); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg); - } - } - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *varptr, *arg; - - SAVE_OPLINE(); - - if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) { - if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - return ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } - } - - varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || - (Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) && - (Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) { - - ZVAL_MAKE_REF(varptr); - if (IS_VAR == IS_CV) { - Z_ADDREF_P(varptr); - } - } else { - if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? - !(opline->extended_value & ZEND_ARG_SEND_SILENT) : - !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - zend_error(E_STRICT, "Only variables should be passed by reference"); - } - } - - arg = ZEND_CALL_ARG(EX(call), opline->op2.num); - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - ZVAL_COPY_VALUE(arg, varptr); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *varptr, *arg; - - SAVE_OPLINE(); - varptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(varptr == NULL)) { - zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); - } - - arg = ZEND_CALL_ARG(EX(call), opline->op2.num); - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - if (IS_VAR == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) { - ZVAL_NEW_REF(arg, &EG(uninitialized_zval)); - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_ISREF_P(varptr)) { - Z_ADDREF_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); - } else if (IS_VAR == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { - ZVAL_NEW_REF(arg, varptr); - } else { - ZVAL_NEW_REF(arg, varptr); - Z_ADDREF_P(arg); - ZVAL_REF(varptr, Z_REF_P(arg)); - } - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - zend_free_op free_op1; - - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } - varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - arg = ZEND_CALL_ARG(EX(call), opline->op2.num); - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(varptr)) { - ZVAL_COPY(arg, Z_REFVAL_P(varptr)); - zval_ptr_dtor_nogc(free_op1); - } else { - ZVAL_COPY_VALUE(arg, varptr); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg); - } - } - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *arg, *param, tmp; - zend_free_op free_op1; - - arg = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - param = ZEND_CALL_ARG(EX(call), opline->op2.num); - - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - // TODO: Scalar values don't have reference counters anymore. - // They are assumed to be 1, and they may be easily passed by - // reference now. However, previously scalars with refcount==1 - // might be passed and with refcount>1 might not. We can support - // only single behavior ??? -#if 0 - if (Z_REFCOUNTED_P(arg) && - // This solution breaks the following test (omit warning message) ??? - // Zend/tests/bug61273.phpt - // ext/reflection/tests/bug42976.phpt - // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt -#else - if (!Z_REFCOUNTED_P(arg) || - // This solution breaks the following test (emit warning message) ??? - // ext/pdo_sqlite/tests/pdo_005.phpt -#endif - (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) { - - if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - - zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", - opline->op2.num, - EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "", - EX(call)->func->common.scope ? "::" : "", - EX(call)->func->common.function_name->val); - - if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { - OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); - } - if (Z_OBJ(EX(call)->This)) { - OBJ_RELEASE(Z_OBJ(EX(call)->This)); - } - EX(call)->func = (zend_function*)&zend_pass_function; - EX(call)->called_scope = NULL; - Z_OBJ(EX(call)->This) = NULL; - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_REFCOUNTED_P(arg)) { - Z_DELREF_P(arg); - } - ZVAL_DUP(&tmp, arg); - ZVAL_NEW_REF(arg, &tmp); - Z_ADDREF_P(arg); - } else if (!Z_ISREF_P(arg)) { - ZVAL_NEW_REF(arg, arg); - Z_ADDREF_P(arg); - } else if (Z_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); - } - ZVAL_COPY_VALUE(param, arg); - } else if (Z_ISREF_P(arg) && - /* don't separate references for __call */ - (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { - ZVAL_DUP(param, Z_REFVAL_P(arg)); - } else { - ZVAL_COPY(param, arg); - } - - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BOOL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *retval = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ - ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1) TSRMLS_CC)); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval object_zval; - zend_function *constructor; - zend_class_entry *ce; - - SAVE_OPLINE(); - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - } - if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { - if (ce->ce_flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val); - } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val); - } else { - zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); - } - } - object_init_ex(&object_zval, ce); - constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC); - - if (constructor == NULL) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); - } else { - OBJ_RELEASE(Z_OBJ(object_zval)); - } - ZEND_VM_JMP(opline->op2.jmp_addr); - } else { - /* We are not handling overloaded classes right now */ - EX(call) = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_CTOR | - (RETURN_VALUE_USED(opline) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED), - constructor, - opline->extended_value, - ce, - Z_OBJ(object_zval), - EX(call) TSRMLS_CC); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); - EX(call)->return_value = EX_VAR(opline->result.var); - } else { - EX(call)->return_value = NULL; - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } -} - -static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *obj; - zend_class_entry *ce; - zend_function *clone; - zend_object_clone_obj_t clone_call; - - SAVE_OPLINE(); - obj = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_CONST || - (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "__clone method called on non-object"); - } - - ce = Z_OBJCE_P(obj); - clone = ce ? ce->clone : NULL; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; - if (UNEXPECTED(clone_call == NULL)) { - if (ce) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); - } else { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); - } - } - - if (ce && clone) { - if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); - } - } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); - } - } - } - - if (EXPECTED(EG(exception) == NULL)) { - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj TSRMLS_CC)); - if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var))); - } - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *expr; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - switch (opline->extended_value) { - case IS_NULL: - /* This code is taken from convert_to_null. However, it does not seems very useful, - * because a conversion to null always results in the same value. This could only - * be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */ -#if 0 - if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { - ZVAL_DEREF(expr); - } - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) { - if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL TSRMLS_CC) == SUCCESS) { - break; - } - } -#endif - - ZVAL_NULL(result); - break; - case _IS_BOOL: - ZVAL_BOOL(result, zend_is_true(expr TSRMLS_CC)); - break; - case IS_LONG: - ZVAL_LONG(result, zval_get_long(expr)); - break; - case IS_DOUBLE: - ZVAL_DOUBLE(result, zval_get_double(expr)); - break; - case IS_STRING: - ZVAL_STR(result, zval_get_string(expr)); - break; - default: - /* If value is already of correct type, return it directly */ - if (Z_TYPE_P(expr) == opline->extended_value) { - ZVAL_COPY_VALUE(result, expr); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) { - zval_copy_ctor_func(result); - } - } else if (IS_VAR != IS_TMP_VAR) { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - if (opline->extended_value == IS_ARRAY) { - if (Z_TYPE_P(expr) != IS_OBJECT) { - ZVAL_NEW_ARR(result); - zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0); - if (Z_TYPE_P(expr) != IS_NULL) { - expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { - zval_copy_ctor_func(expr); - } - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } - } else { - ZVAL_COPY_VALUE(result, expr); - Z_ADDREF_P(result); - convert_to_array(result); - } - } else { - if (Z_TYPE_P(expr) != IS_ARRAY) { - object_init(result); - if (Z_TYPE_P(expr) != IS_NULL) { - expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { - zval_copy_ctor_func(expr); - } - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } - } else { - ZVAL_COPY_VALUE(result, expr); - zval_opt_copy_ctor(result); - convert_to_object(result); - } - } - } - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_op_array *new_op_array=NULL; - zend_free_op free_op1; - zval *inc_filename; - zval tmp_inc_filename; - zend_bool failure_retval=0; - - SAVE_OPLINE(); - inc_filename = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp_inc_filename); - if (Z_TYPE_P(inc_filename) != IS_STRING) { - ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); - inc_filename = &tmp_inc_filename; - } - - if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) { - if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) { - zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); - } else { - zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); - } - } else { - switch (opline->extended_value) { - case ZEND_INCLUDE_ONCE: - case ZEND_REQUIRE_ONCE: { - zend_file_handle file_handle; - char *resolved_path; - - resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename) TSRMLS_CC); - if (resolved_path) { - failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path)); - } else { - resolved_path = Z_STRVAL_P(inc_filename); - } - - if (failure_retval) { - /* do nothing, file already included */ - } else if (SUCCESS == zend_stream_open(resolved_path, &file_handle TSRMLS_CC)) { - - if (!file_handle.opened_path) { - file_handle.opened_path = estrdup(resolved_path); - } - - if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) { - new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC); - zend_destroy_file_handle(&file_handle TSRMLS_CC); - } else { - zend_file_handle_dtor(&file_handle TSRMLS_CC); - failure_retval=1; - } - } else { - if (opline->extended_value == ZEND_INCLUDE_ONCE) { - zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); - } else { - zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); - } - } - if (resolved_path != Z_STRVAL_P(inc_filename)) { - efree(resolved_path); - } - } - break; - case ZEND_INCLUDE: - case ZEND_REQUIRE: - new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC); - break; - case ZEND_EVAL: { - char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); - - new_op_array = zend_compile_string(inc_filename, eval_desc TSRMLS_CC); - efree(eval_desc); - } - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) { - zend_string_release(Z_STR(tmp_inc_filename)); - } - zval_ptr_dtor_nogc(free_op1); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } else if (EXPECTED(new_op_array != NULL)) { - zval *return_value = NULL; - zend_execute_data *call; - - if (RETURN_VALUE_USED(opline)) { - return_value = EX_VAR(opline->result.var); - } - - new_op_array->scope = EG(scope); /* ??? */ - - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, - (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL TSRMLS_CC); - - if (EX(symbol_table)) { - call->symbol_table = EX(symbol_table); - } else { - call->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); - } - - call->prev_execute_data = execute_data; - i_init_code_execute_data(call, new_op_array, return_value TSRMLS_CC); - if (EXPECTED(zend_execute_ex == execute_ex)) { - ZEND_VM_ENTER(); - } else { - ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); - zend_execute_ex(call TSRMLS_CC); - } - - destroy_op_array(new_op_array TSRMLS_CC); - efree_size(new_op_array, sizeof(zend_op_array)); - if (UNEXPECTED(EG(exception) != NULL)) { - zend_throw_exception_internal(NULL TSRMLS_CC); - HANDLE_EXCEPTION(); - } - - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_BOOL(EX_VAR(opline->result.var), failure_retval); - } - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *array_ptr, *array_ref, iterator, tmp; - HashTable *fe_ht; - zend_object_iterator *iter = NULL; - zend_class_entry *ce = NULL; - zend_bool is_empty = 0; - - SAVE_OPLINE(); - - if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && - (opline->extended_value & ZEND_FE_FETCH_BYREF)) { - array_ptr = array_ref = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - ZVAL_DEREF(array_ptr); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); - if (!Z_ISREF_P(array_ref)) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); - } - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce->get_iterator == NULL) { - Z_ADDREF_P(array_ptr); - } - array_ref = array_ptr; - } else { - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } - } else { - array_ptr = array_ref = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - ZVAL_DEREF(array_ptr); - if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&tmp, array_ptr); - if (Z_OPT_IMMUTABLE_P(&tmp)) { - zval_copy_ctor_func(&tmp); - } - array_ref = array_ptr = &tmp; - if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce && ce->get_iterator) { - Z_DELREF_P(array_ref); - } - } - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (!ce->get_iterator) { - if (IS_VAR == IS_CV) { - Z_ADDREF_P(array_ref); - } - } - } else if (Z_IMMUTABLE_P(array_ref)) { - if (IS_VAR == IS_CV) { - zval_copy_ctor_func(array_ref); - Z_ADDREF_P(array_ref); - } else { - ZVAL_COPY_VALUE(&tmp, array_ref); - zval_copy_ctor_func(&tmp); - array_ptr = array_ref = &tmp; - } - } else if (Z_REFCOUNTED_P(array_ref)) { - if (IS_VAR == IS_CONST || - (IS_VAR == IS_CV && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 1) || - (IS_VAR == IS_VAR && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 2)) { - if (IS_VAR == IS_VAR) { - Z_DELREF_P(array_ref); - } - ZVAL_DUP(&tmp, array_ref); - array_ptr = array_ref = &tmp; - } else if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) { - ZVAL_UNREF(array_ref); - array_ptr = array_ref; - } - if (Z_IMMUTABLE_P(array_ptr)) { - zval_copy_ctor_func(array_ptr); - } else if (Z_ISREF_P(array_ref) && - Z_COPYABLE_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1) { - Z_DELREF_P(array_ptr); - zval_copy_ctor_func(array_ptr); - } - if (IS_VAR == IS_CV) { - Z_ADDREF_P(array_ref); - } - } - } - } - - if (ce && ce->get_iterator) { - iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF TSRMLS_CC); - - if (IS_VAR == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) { - zval_ptr_dtor_nogc(free_op1); - } - if (iter && EXPECTED(EG(exception) == NULL)) { - ZVAL_OBJ(&iterator, &iter->std); - array_ptr = array_ref = &iterator; - } else { - if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name->val); - } - zend_throw_exception_internal(NULL TSRMLS_CC); - HANDLE_EXCEPTION(); - } - } - - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - - if (iter) { - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } - HANDLE_EXCEPTION(); - } - } - is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS; - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ - } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var); - HashPosition pos = 0; - Bucket *p; - - while (1) { - if (pos >= fe_ht->nNumUsed) { - is_empty = 1; - if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } - ZEND_VM_JMP(opline->op2.jmp_addr); - } - p = fe_ht->arData + pos; - if (Z_TYPE(p->val) == IS_UNDEF || - (Z_TYPE(p->val) == IS_INDIRECT && - Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) { - pos++; - continue; - } - if (!ce || - !p->key || - zend_check_property_access(Z_OBJ_P(array_ptr), p->key TSRMLS_CC) == SUCCESS) { - break; - } - pos++; - } - fe_ht->nInternalPointer = pos; - ptr->pos = pos; - ptr->ht = fe_ht; - ptr->h = fe_ht->arData[pos].h; - ptr->key = fe_ht->arData[pos].key; - is_empty = 0; - } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - is_empty = 1; - } - - if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } - if (is_empty) { - ZEND_VM_JMP(opline->op2.jmp_addr); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } -} - -static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *array, *array_ref; - zval *value; - HashTable *fe_ht; - HashPointer *ptr; - HashPosition pos; - Bucket *p; - - array = array_ref = EX_VAR(opline->op1.var); - if (Z_ISREF_P(array)) { - array = Z_REFVAL_P(array); - // TODO: referenced value might be changed to different array ??? - if (Z_IMMUTABLE_P(array)) { - zval_copy_ctor_func(array); - } - } - - SAVE_OPLINE(); - - if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { - fe_ht = Z_ARRVAL_P(array); - ptr = (HashPointer*)EX_VAR((opline+1)->op1.var); - pos = ptr->pos; - if (UNEXPECTED(pos == INVALID_IDX)) { - /* reached end of iteration */ - ZEND_VM_JMP(opline->op2.jmp_addr); - } else if (UNEXPECTED(ptr->ht != fe_ht)) { - ptr->ht = fe_ht; - pos = 0; - } else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) { - if (fe_ht->u.flags & HASH_FLAG_PACKED) { - pos = ptr->h; - } else { - pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask]; - while (1) { - if (pos == INVALID_IDX) { - pos = fe_ht->nInternalPointer; - break; - } else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) { - break; - } - pos = Z_NEXT(fe_ht->arData[pos].val); - } - } - } - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - ZEND_VM_JMP(opline->op2.jmp_addr); - } - p = fe_ht->arData + pos; - value = &p->val; - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - pos++; - continue; - } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) { - value = Z_INDIRECT_P(value); - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - pos++; - continue; - } - } - if (opline->extended_value & ZEND_FE_FETCH_BYREF) { - ZVAL_MAKE_REF(value); - Z_ADDREF_P(value); - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); - } else { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { - if (!p->key) { - ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key); - } - } - break; - } - do { - pos++; - if (pos >= fe_ht->nNumUsed) { - fe_ht->nInternalPointer = ptr->pos = INVALID_IDX; - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); - } - p = fe_ht->arData + pos; - } while (Z_TYPE(p->val) == IS_UNDEF || - (Z_TYPE(p->val) == IS_INDIRECT && - Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)); - fe_ht->nInternalPointer = ptr->pos = pos; - ptr->h = fe_ht->arData[pos].h; - ptr->key = fe_ht->arData[pos].key; - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); - } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { - zend_object_iterator *iter; - - if ((iter = zend_iterator_unwrap(array TSRMLS_CC)) == NULL) { - /* plain object */ - zend_object *zobj = Z_OBJ_P(array); - - fe_ht = Z_OBJPROP_P(array); - ptr = (HashPointer*)EX_VAR((opline+1)->op1.var); - pos = ptr->pos; - if (pos == INVALID_IDX) { - /* reached end of iteration */ - ZEND_VM_JMP(opline->op2.jmp_addr); - } else if (UNEXPECTED(ptr->ht != fe_ht)) { - ptr->ht = fe_ht; - pos = 0; - } else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) { - if (fe_ht->u.flags & HASH_FLAG_PACKED) { - pos = ptr->h; - } else { - pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask]; - while (1) { - if (pos == INVALID_IDX) { - pos = fe_ht->nInternalPointer; - break; - } else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) { - break; - } - pos = Z_NEXT(fe_ht->arData[pos].val); - } - } - } - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - ZEND_VM_JMP(opline->op2.jmp_addr); - } - - p = fe_ht->arData + pos; - value = &p->val; - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - pos++; - continue; - } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) { - value = Z_INDIRECT_P(value); - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - pos++; - continue; - } - } - - if (UNEXPECTED(!p->key)) { - if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { - ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h); - } - break; - } else if (zend_check_property_access(zobj, p->key TSRMLS_CC) == SUCCESS) { - if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { - if (p->key->val[0]) { - ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key); - } else { - const char *class_name, *prop_name; - size_t prop_name_len; - zend_unmangle_property_name_ex( - p->key, &class_name, &prop_name, &prop_name_len); - ZVAL_STRINGL(EX_VAR((opline+1)->result.var), prop_name, prop_name_len); - } - } - break; - } - pos++; - } - if (opline->extended_value & ZEND_FE_FETCH_BYREF) { - ZVAL_MAKE_REF(value); - Z_ADDREF_P(value); - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); - } else { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - do { - pos++; - if (pos >= fe_ht->nNumUsed) { - fe_ht->nInternalPointer = ptr->pos = INVALID_IDX; - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); - } - p = fe_ht->arData + pos; - } while (Z_TYPE(p->val) == IS_UNDEF || - (Z_TYPE(p->val) == IS_INDIRECT && - Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) || - (EXPECTED(p->key != NULL) && - zend_check_property_access(zobj, p->key TSRMLS_CC) == FAILURE)); - fe_ht->nInternalPointer = ptr->pos = pos; - ptr->h = fe_ht->arData[pos].h; - ptr->key = fe_ht->arData[pos].key; - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); - } else { - /* !iter happens from exception */ - if (iter && ++iter->index > 0) { - /* This could cause an endless loop if index becomes zero again. - * In case that ever happens we need an additional flag. */ - iter->funcs->move_forward(iter TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - HANDLE_EXCEPTION(); - } - } - /* If index is zero we come from FE_RESET and checked valid() already. */ - if (!iter || (iter->index > 0 && iter->funcs->valid(iter TSRMLS_CC) == FAILURE)) { - /* reached end of iteration */ - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline->op2.jmp_addr); - } - value = iter->funcs->get_current_data(iter TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - HANDLE_EXCEPTION(); - } - if (!value) { - /* failure in get_current_data */ - ZEND_VM_JMP(opline->op2.jmp_addr); - } - if (opline->extended_value & ZEND_FE_FETCH_BYREF) { - ZVAL_MAKE_REF(value); - Z_ADDREF_P(value); - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); - } else { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { - if (iter->funcs->get_current_key) { - iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var) TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - HANDLE_EXCEPTION(); - } - } else { - ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index); - } - } - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); - } - } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } -} - -static int ZEND_FASTCALL ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 || (IS_VAR != IS_UNUSED) - USE_OPLINE - - SAVE_OPLINE(); - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - zval *ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (Z_TYPE_P(ptr) == IS_LONG) { - EG(exit_status) = Z_LVAL_P(ptr); - } else { - zend_print_variable(ptr TSRMLS_CC); - } - zval_ptr_dtor_nogc(free_op1); - } -#endif - zend_bailout(); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ -} - -static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *value; - int is_ref = 0; - - SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { - is_ref = 1; - value = Z_REFVAL_P(value); - } - if (i_zend_is_true(value TSRMLS_CC)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { - zval_copy_ctor_func(EX_VAR(opline->result.var)); - } - } else if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } else if (IS_VAR == IS_VAR && is_ref) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - zval_ptr_dtor_nogc(free_op1); - } - ZEND_VM_JMP(opline->op2.jmp_addr); - } - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *value; - int is_ref = 0; - - SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { - is_ref = 1; - value = Z_REFVAL_P(value); - } - - if (Z_TYPE_P(value) > IS_NULL) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { - zval_copy_ctor_func(EX_VAR(opline->result.var)); - } - } else if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } else if (IS_VAR == IS_VAR && is_ref) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - zval_ptr_dtor_nogc(free_op1); - } - ZEND_VM_JMP(opline->op2.jmp_addr); - } - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *value; - - SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { - ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); - } else { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { - zval_copy_ctor_func(EX_VAR(opline->result.var)); - } - } else if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_STRLEN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zend_free_op free_op1; - - SAVE_OPLINE(); - value = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - } else { - if (Z_TYPE_P(value) < IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 0); - } else if (Z_TYPE_P(value) == IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 1); - } else if (Z_TYPE_P(value) <= IS_DOUBLE) { - zend_string *str = zval_get_string(value); - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); - } else if (Z_TYPE_P(value) == IS_OBJECT) { - zend_string *str; - zval tmp; - - ZVAL_COPY(&tmp, value); - if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) { - goto strlen_error; - } - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zval_dtor(&tmp); - } else { -strlen_error: - zend_error(E_WARNING, "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)); - } - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zend_free_op free_op1; - - SAVE_OPLINE(); - value = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - switch (opline->extended_value) { - case IS_NULL: - case IS_LONG: - case IS_DOUBLE: - case IS_STRING: - case IS_ARRAY: - ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == opline->extended_value); - break; - case _IS_BOOL: - ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE); - break; - case IS_OBJECT: - if (Z_TYPE_P(value) == opline->extended_value) { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } - } else { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } - break; - case IS_RESOURCE: - if (Z_TYPE_P(value) == opline->extended_value) { - const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value) TSRMLS_CC); - ZVAL_BOOL(EX_VAR(opline->result.var), type_name != NULL); - } else { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - fast_mod_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - shift_left_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - shift_right_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - concat_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - fast_is_identical_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_is_not_identical_function(result, - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - bitwise_or_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - bitwise_and_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - bitwise_xor_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - - SAVE_OPLINE(); - boolean_xor_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op_data1; - zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - zval *property = opline->op2.zv; - zval *value; - zval *zptr; - - if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - - if (IS_VAR != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); - } - - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - - FREE_OP(free_op_data1); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - /* here we are sure we are dealing with an object */ - if (opline->extended_value == ZEND_ASSIGN_OBJ - && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } else { - zval *z = NULL; - zval rv; - - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - } - } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv TSRMLS_CC); - } - } - if (z) { - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } -//??? if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - binary_op(z, z, value TSRMLS_CC); - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), z); - } - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } - } - - FREE_OP(free_op_data1); - } - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - /* assign_obj has two opcodes! */ - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op_data1; - zval *var_ptr, rv; - zval *value, *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - if (IS_VAR != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_VAR == IS_VAR && !(free_op1 != NULL)) { - Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ - } - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zval *dim = opline->op2.zv; - - zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - } - - if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } - - if (UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - binary_op(var_ptr, var_ptr, value TSRMLS_CC); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - } - - FREE_OP(free_op_data1); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *var_ptr; - zval *value; - - SAVE_OPLINE(); - value = opline->op2.zv; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } - - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - binary_op(var_ptr, var_ptr, value TSRMLS_CC); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - } - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *object; - zval *property; - zval *retval; - zval *zptr; - - SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property = opline->op2.zv; - retval = EX_VAR(opline->result.var); - - if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (IS_VAR != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } - - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - /* here we are sure we are dealing with an object */ - - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } else { - zval rv; - - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - incdec_op(z); - ZVAL_COPY_VALUE(retval, z); - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - SELECTIVE_PZVAL_LOCK(retval, opline); - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); - } - } - } - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_VAR_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_VAR_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *object; - zval *property; - zval *retval; - zval *zptr; - - SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property = opline->op2.zv; - retval = EX_VAR(opline->result.var); - - if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (IS_VAR != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } - - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - - ZVAL_NULL(retval); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - /* here we are sure we are dealing with an object */ - - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - - ZVAL_DEREF(zptr); - ZVAL_COPY_VALUE(retval, zptr); - zval_opt_copy_ctor(zptr); - - incdec_op(zptr); - } else { - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval rv; - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - zval z_copy; - - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } - ZVAL_DUP(retval, z); - ZVAL_DUP(&z_copy, z); - incdec_op(&z_copy); - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - zval_ptr_dtor(&z_copy); - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - ZVAL_NULL(retval); - } - } - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_post_incdec_property_helper_SPEC_VAR_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_post_incdec_property_helper_SPEC_VAR_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *varname; - zval *retval; - zend_string *name; - HashTable *target_symbol_table; - - SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - zend_string_addref(name); - } else { - name = zval_get_string(varname); - } - - if (IS_CONST != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - if (IS_VAR != IS_CONST) { - zend_string_release(name); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - retval = zend_std_get_static_property(ce, name, 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - retval = zend_hash_find(target_symbol_table, name); - if (retval == NULL) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1 TSRMLS_CC); - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - zval_ptr_dtor_nogc(free_op1); - } - } - - if (IS_VAR != IS_CONST) { - zend_string_release(name); - } - - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { - ZVAL_UNREF(retval); - } - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - zend_free_op free_op1; - - SAVE_OPLINE(); - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } else { - if (IS_CONST == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op1); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = opline->op2.zv; - - if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); - } - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *property; - zval *container; - - SAVE_OPLINE(); - property = opline->op2.zv; - - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *property; - zval *container; - - SAVE_OPLINE(); - property = opline->op2.zv; - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); - - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = opline->op2.zv; - - if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); - } - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1; - zval *property; - - SAVE_OPLINE(); - property = opline->op2.zv; - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } else { - return ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container, *property; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property = opline->op2.zv; - - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); - - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - - zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); - - ZVAL_COPY(EX_VAR(opline->result.var), value); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) && - EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) { - zval *result = EX_VAR(opline->result.var); - zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, opline->op2.zv, BP_VAR_R, result TSRMLS_CC); - - if (retval) { - if (result != retval) { - ZVAL_COPY(result, retval); - } - } else { - ZVAL_NULL(result); - } - } else { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *object; - zval *property_name; - - SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property_name = opline->op2.zv; - - if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - /* assign_obj has two opcodes! */ - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *object_ptr; - - SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(object_ptr); - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - - zval *property_name = opline->op2.zv; - - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - - } else { - zend_free_op free_op_data1; - zval rv; - zval *value; - zval *dim = opline->op2.zv; - zval *variable_ptr; - - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && - EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - FREE_OP(free_op_data1); - } else { - zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST TSRMLS_CC); - - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - variable_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); - if ((opline+1)->op1_type == IS_VAR) { - FREE_OP(free_op_data1); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - } - } - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - /* assign_dim has two opcodes! */ - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = opline->op2.zv; - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_CONST == IS_TMP_VAR) { - - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CONST TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *function_name; - zend_free_op free_op1; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; - - SAVE_OPLINE(); - - function_name = opline->op2.zv; - - if (IS_CONST != IS_CONST && - UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Method name must be a string"); - } - - object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - - zval_ptr_dtor_nogc(free_op1); - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); - } - - obj = Z_OBJ_P(object); - called_scope = obj->ce; - - if (IS_CONST != IS_CONST || - EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { - zend_object *orig_obj = obj; - - if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); - } - - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(obj == orig_obj)) { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); - } - } - - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; - } else { - GC_REFCOUNT(obj)++; /* For $this pointer */ - } - - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op1); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *function_name; - zend_class_entry *ce; - zend_object *object; - zend_function *fbc; - - SAVE_OPLINE(); - - if (IS_VAR == IS_CONST) { - /* no function found. try a static method in class */ - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - } - - if (IS_VAR == IS_CONST && - IS_CONST == IS_CONST && - CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else if (IS_VAR != IS_CONST && - IS_CONST == IS_CONST && - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) { - /* do nothing */ - } else if (IS_CONST != IS_UNUSED) { - - - function_name = opline->op2.zv; - if (IS_CONST != IS_CONST) { - if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Function name must be a string"); - } - } - - if (ce->get_static_method) { - fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC); - } else { - fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - } - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { - if (IS_VAR == IS_CONST) { - CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc); - } else { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc); - } - } - if (IS_CONST != IS_CONST) { - - } - } else { - if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); - } - if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); - } - fbc = ce->constructor; - } - - object = NULL; - if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_OBJ(EX(This))) { - object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; - } - if (!object || - !instanceof_function(object->ce, ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); - } - } - } - - if (IS_VAR != IS_CONST) { - /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EX(called_scope); - } - } - - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); - - if (IS_CONST == IS_UNUSED) { - EX(call)->return_value = NULL; - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - SAVE_OPLINE(); - if (IS_VAR == IS_UNUSED) { - zend_constant *c; - zval *retval; - - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - c = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else if ((c = zend_quick_get_constant(opline->op2.zv + 1, opline->extended_value TSRMLS_CC)) == NULL) { - if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { - char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); - if (!actual) { - ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(opline->op2.zv))); - } else { - actual++; - ZVAL_STRINGL(EX_VAR(opline->result.var), - actual, Z_STRLEN_P(opline->op2.zv) - (actual - Z_STRVAL_P(opline->op2.zv))); - } - /* non-qualified constant - allow text substitution */ - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", - Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } else { - zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv)); - } - } else { - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), c); - } - retval = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(retval, &c->value); - if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) { - if (Z_OPT_COPYABLE_P(retval)) { - zval_copy_ctor_func(retval); - } else { - Z_ADDREF_P(retval); - } - } - } else { - /* class constant */ - zend_class_entry *ce; - zval *value; - - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - value = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - goto constant_fetch_end; - } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce)) != NULL) { - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - goto constant_fetch_end; - } - } - - if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) { - ZVAL_DEREF(value); - if (Z_CONSTANT_P(value)) { - EG(scope) = ce; - zval_update_constant(value, 1 TSRMLS_CC); - EG(scope) = EX(func)->op_array.scope; - } - if (IS_VAR == IS_CONST) { - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), value); - } else { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce, value); - } - ZVAL_DUP(EX_VAR(opline->result.var), value); - } else if (Z_STRLEN_P(opline->op2.zv) == sizeof("class")-1 && memcmp(Z_STRVAL_P(opline->op2.zv), "class", sizeof("class") - 1) == 0) { - /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ - ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); - } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv)); - } - } -constant_fetch_end: - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *expr_ptr, new_expr; - - SAVE_OPLINE(); - if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); - } - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } else if (IS_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } - } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) { - expr_ptr = Z_REFVAL_P(expr_ptr); - if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); - zval_ptr_dtor_nogc(free_op1); - } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } - } - - if (IS_CONST != IS_UNUSED) { - - zval *offset = opline->op2.zv; - zend_string *str; - zend_ulong hval; - -add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; - } - - } else { - zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zval *array; - uint32_t size; - USE_OPLINE - - array = EX_VAR(opline->result.var); - if (IS_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_NEW_ARR(array); - zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); - - if (IS_VAR != IS_UNUSED) { - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init(Z_ARRVAL_P(array), 0); - } - } - - if (IS_VAR == IS_UNUSED) { - ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_VAR != IS_UNUSED - } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#endif - } -} - -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval tmp, *varname; - HashTable *target_symbol_table; - zend_free_op free_op1; - - SAVE_OPLINE(); - if (IS_VAR == IS_CV && - IS_CONST == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - zval *var = EX_VAR(opline->op1.var); - - if (Z_REFCOUNTED_P(var)) { - zend_refcounted *garbage = Z_COUNTED_P(var); - - if (!--GC_REFCOUNT(garbage)) { - ZVAL_UNDEF(var); - _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); - } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); - } - } else { - ZVAL_UNDEF(var); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_CONST != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { + fe_ht = Z_ARRVAL_P(array); + ptr = (HashPointer*)EX_VAR((opline+1)->op1.var); + pos = ptr->pos; + if (UNEXPECTED(pos == INVALID_IDX)) { + /* reached end of iteration */ + ZEND_VM_JMP(opline->op2.jmp_addr); + } else if (UNEXPECTED(ptr->ht != fe_ht)) { + ptr->ht = fe_ht; + pos = 0; + } else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) { + if (fe_ht->u.flags & HASH_FLAG_PACKED) { + pos = ptr->h; } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); + pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask]; + while (1) { + if (pos == INVALID_IDX) { + pos = fe_ht->nInternalPointer; + break; + } else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) { + break; } - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); + pos = Z_NEXT(fe_ht->arData[pos].val); } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); } - zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - zval *offset; - zend_ulong hval; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - if (IS_VAR != IS_UNUSED) { - ZVAL_DEREF(container); - } - SEPARATE_ZVAL_NOREF(container); - offset = opline->op2.zv; - - if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); -offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_JMP(opline->op2.jmp_addr); + } + p = fe_ht->arData + pos; + value = &p->val; + if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + pos++; + continue; + } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) { + value = Z_INDIRECT_P(value); + if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + pos++; + continue; } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } + if (opline->extended_value & ZEND_FE_FETCH_BYREF) { + ZVAL_MAKE_REF(value); + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); + } else { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { + if (!p->key) { + ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h); } else { - zend_hash_del(ht, Z_STR_P(offset)); + ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - - } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CONST == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - offset = opline->op2.zv; - - if (IS_VAR != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->unset_property) { - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to unset property of non-object"); - } - } - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - - SAVE_OPLINE(); - if (IS_VAR == IS_CV && - IS_CONST == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - value = EX_VAR(opline->op1.var); - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !i_zend_is_true(value TSRMLS_CC)); - CHECK_EXCEPTION(); + } + break; } + do { + pos++; + if (pos >= fe_ht->nNumUsed) { + fe_ht->nInternalPointer = ptr->pos = INVALID_IDX; + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); + } + p = fe_ht->arData + pos; + } while (Z_TYPE(p->val) == IS_UNDEF || + (Z_TYPE(p->val) == IS_INDIRECT && + Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)); + fe_ht->nInternalPointer = ptr->pos = pos; + ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); - } else { - zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } + } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { + zend_object_iterator *iter; - if (IS_CONST != IS_UNUSED) { - zend_class_entry *ce; + if ((iter = zend_iterator_unwrap(array TSRMLS_CC)) == NULL) { + /* plain object */ + zend_object *zobj = Z_OBJ_P(array); - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + fe_ht = Z_OBJPROP_P(array); + ptr = (HashPointer*)EX_VAR((opline+1)->op1.var); + pos = ptr->pos; + if (pos == INVALID_IDX) { + /* reached end of iteration */ + ZEND_VM_JMP(opline->op2.jmp_addr); + } else if (UNEXPECTED(ptr->ht != fe_ht)) { + ptr->ht = fe_ht; + pos = 0; + } else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) { + if (fe_ht->u.flags & HASH_FLAG_PACKED) { + pos = ptr->h; } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask]; + while (1) { + if (pos == INVALID_IDX) { + pos = fe_ht->nInternalPointer; + break; + } else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) { + break; + } + pos = Z_NEXT(fe_ht->arData[pos].val); } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); } - value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - value && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !value || !i_zend_is_true(value TSRMLS_CC)); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - int result; - zend_ulong hval; - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = opline->op2.zv; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_JMP(opline->op2.jmp_addr); + } - if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); - zval *value; - zend_string *str; + p = fe_ht->arData + pos; + value = &p->val; + if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + pos++; + continue; + } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) { + value = Z_INDIRECT_P(value); + if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + pos++; + continue; + } + } -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; + if (UNEXPECTED(!p->key)) { + if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { + ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h); + } + break; + } else if (zend_check_property_access(zobj, p->key TSRMLS_CC) == SUCCESS) { + if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { + if (p->key->val[0]) { + ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key); + } else { + const char *class_name, *prop_name; + size_t prop_name_len; + zend_unmangle_property_name_ex( + p->key, &class_name, &prop_name, &prop_name_len); + ZVAL_STRINGL(EX_VAR((opline+1)->result.var), prop_name, prop_name_len); + } + } + break; } + pos++; } -str_index_prop: - value = zend_hash_find_ind(ht, str); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - value = NULL; - break; + if (opline->extended_value & ZEND_FE_FETCH_BYREF) { + ZVAL_MAKE_REF(value); + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); + } else { + ZVAL_COPY(EX_VAR(opline->result.var), value); } - } - - if (opline->extended_value & ZEND_ISSET) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); - } - } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { - result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + do { + pos++; + if (pos >= fe_ht->nNumUsed) { + fe_ht->nInternalPointer = ptr->pos = INVALID_IDX; + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); + } + p = fe_ht->arData + pos; + } while (Z_TYPE(p->val) == IS_UNDEF || + (Z_TYPE(p->val) == IS_INDIRECT && + Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) || + (EXPECTED(p->key != NULL) && + zend_check_property_access(zobj, p->key TSRMLS_CC) == FAILURE)); + fe_ht->nInternalPointer = ptr->pos = pos; + ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); } else { - zend_error(E_NOTICE, "Trying to check element of non-array"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ - zval tmp; - - result = 0; - if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - ZVAL_DEREF(offset); + /* !iter happens from exception */ + if (iter && ++iter->index > 0) { + /* This could cause an endless loop if index becomes zero again. + * In case that ever happens we need an additional flag. */ + iter->funcs->move_forward(iter TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array_ref); + HANDLE_EXCEPTION(); + } } - if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ - || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ - && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { - ZVAL_DUP(&tmp, offset); - convert_to_long(&tmp); - offset = &tmp; + /* If index is zero we come from FE_RESET and checked valid() already. */ + if (!iter || (iter->index > 0 && iter->funcs->valid(iter TSRMLS_CC) == FAILURE)) { + /* reached end of iteration */ + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array_ref); + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline->op2.jmp_addr); } - } - if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { - if ((opline->extended_value & ZEND_ISSET) || - Z_STRVAL_P(container)[offset->value.lval] != '0') { - result = 1; + value = iter->funcs->get_current_data(iter TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array_ref); + HANDLE_EXCEPTION(); + } + if (!value) { + /* failure in get_current_data */ + ZEND_VM_JMP(opline->op2.jmp_addr); + } + if (opline->extended_value & ZEND_FE_FETCH_BYREF) { + ZVAL_MAKE_REF(value); + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); + } else { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { + if (iter->funcs->get_current_key) { + iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var) TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array_ref); + HANDLE_EXCEPTION(); + } + } else { + ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index); } } - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); } } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + ZEND_VM_JMP(opline->op2.jmp_addr); } - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 || (IS_VAR != IS_UNUSED) USE_OPLINE - zend_free_op free_op1; - zval *container; - int result; - zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = opline->op2.zv; + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + zval *ptr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + if (Z_TYPE_P(ptr) == IS_LONG) { + EG(exit_status) = Z_LVAL_P(ptr); } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; + zend_print_variable(ptr TSRMLS_CC); } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + zval_ptr_dtor_nogc(free_op1); } - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); +#endif + zend_bailout(); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } -static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *expr; - zend_bool result; + zval *value; + int is_ref = 0; SAVE_OPLINE(); - expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { + is_ref = 1; + value = Z_REFVAL_P(value); + } + if (i_zend_is_true(value TSRMLS_CC)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); + } else if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } else if (IS_VAR == IS_VAR && is_ref) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + zval_ptr_dtor_nogc(free_op1); } - result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); - } else { - result = 0; + ZEND_VM_JMP(opline->op2.jmp_addr); } - ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op1; + zval *value; + int is_ref = 0; - /* The generator object is stored in EX(return_value) */ - zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { + is_ref = 1; + value = Z_REFVAL_P(value); } - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); - } - } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); - } - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - } else { - ZVAL_MAKE_REF(value_ptr); - } - ZVAL_COPY(&generator->value, value_ptr); - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } - } else { - zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } + if (Z_TYPE_P(value) > IS_NULL) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); } + } else if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } else if (IS_VAR == IS_VAR && is_ref) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + zval_ptr_dtor_nogc(free_op1); } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); + ZEND_VM_JMP(opline->op2.jmp_addr); } - /* Set the new yielded key */ - if (IS_CONST != IS_UNUSED) { + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - zval *key = opline->op2.zv; +static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value; - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->key, key); - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { + ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(free_op1); + } else { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); } + } else if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; } + ZEND_VM_NEXT_OPCODE(); +} - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); +static int ZEND_FASTCALL ZEND_STRLEN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zend_free_op free_op1; - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ SAVE_OPLINE(); + value = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + } else { + if (Z_TYPE_P(value) < IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 0); + } else if (Z_TYPE_P(value) == IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 1); + } else if (Z_TYPE_P(value) <= IS_DOUBLE) { + zend_string *str = zval_get_string(value); + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zend_string_release(str); + } else if (Z_TYPE_P(value) == IS_OBJECT) { + zend_string *str; + zval tmp; - ZEND_VM_RETURN(); + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) { + goto strlen_error; + } + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zval_dtor(&tmp); + } else { +strlen_error: + zend_error(E_WARNING, "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)); + } + } + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *value; zend_free_op free_op1; SAVE_OPLINE(); - pow_function(EX_VAR(opline->result.var), - _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); + value = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + switch (opline->extended_value) { + case IS_NULL: + case IS_LONG: + case IS_DOUBLE: + case IS_STRING: + case IS_ARRAY: + ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == opline->extended_value); + break; + case _IS_BOOL: + ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE); + break; + case IS_OBJECT: + if (Z_TYPE_P(value) == opline->extended_value) { + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } else { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } + break; + case IS_RESOURCE: + if (Z_TYPE_P(value) == opline->extended_value) { + const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value) TSRMLS_CC); + ZVAL_BOOL(EX_VAR(opline->result.var), type_name != NULL); + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } + break; + EMPTY_SWITCH_DEFAULT_CASE() + } zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_binary_assign_op_helper_SPEC_VAR_CONST(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); fast_mod_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); shift_left_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); shift_right_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); concat_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); fast_is_identical_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); fast_is_not_identical_function(result, _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); bitwise_or_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); bitwise_and_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); bitwise_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); boolean_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data1; + zend_free_op free_op1, free_op_data1; zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zval *property = opline->op2.zv; zval *value; zval *zptr; @@ -19547,7 +14841,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); - zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -19557,7 +14851,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); SEPARATE_ZVAL_NOREF(zptr); @@ -19572,7 +14866,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin if (opline->extended_value == ZEND_ASSIGN_OBJ) { if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); } } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { if (Z_OBJ_HT_P(object)->read_dimension) { @@ -19593,7 +14887,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin SEPARATE_ZVAL_IF_NOT_REF(z); binary_op(z, z, value TSRMLS_CC); if (opline->extended_value == ZEND_ASSIGN_OBJ) { - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } @@ -19609,7 +14903,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin } } - zval_ptr_dtor_nogc(free_op2); FREE_OP(free_op_data1); } @@ -19620,10 +14913,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data1; + zend_free_op free_op1, free_op_data1; zval *var_ptr, rv; zval *value, *container; @@ -19639,11 +14932,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin if (IS_VAR == IS_VAR && !(free_op1 != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zval *dim = opline->op2.zv; - zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); var_ptr = Z_INDIRECT(rv); @@ -19668,7 +14961,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin } } - zval_ptr_dtor_nogc(free_op2); FREE_OP(free_op_data1); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); @@ -19676,15 +14968,15 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *var_ptr; zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + value = opline->op2.zv; var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -19706,159 +14998,158 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ } } - zval_ptr_dtor_nogc(free_op2); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *object; zval *property; zval *retval; @@ -19866,7 +15157,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; retval = EX_VAR(opline->result.var); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { @@ -19879,7 +15170,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); + if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(retval); } @@ -19891,7 +15182,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i /* here we are sure we are dealing with an object */ if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); SEPARATE_ZVAL_NOREF(zptr); @@ -19904,7 +15195,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { zval rv; @@ -19919,7 +15210,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i SEPARATE_ZVAL_IF_NOT_REF(z); incdec_op(z); ZVAL_COPY_VALUE(retval, z); - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); SELECTIVE_PZVAL_LOCK(retval, opline); zval_ptr_dtor(z); } else { @@ -19930,26 +15221,25 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i } } - zval_ptr_dtor_nogc(free_op2); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_pre_incdec_property_helper_SPEC_VAR_TMP(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_pre_incdec_property_helper_SPEC_VAR_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_pre_incdec_property_helper_SPEC_VAR_TMP(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_pre_incdec_property_helper_SPEC_VAR_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *object; zval *property; zval *retval; @@ -19957,7 +15247,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; retval = EX_VAR(opline->result.var); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { @@ -19970,7 +15260,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); + ZVAL_NULL(retval); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); @@ -19980,7 +15270,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t /* here we are sure we are dealing with an object */ if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); ZVAL_COPY_VALUE(retval, zptr); @@ -19990,7 +15280,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); zval z_copy; if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { @@ -20006,7 +15296,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t ZVAL_DUP(&z_copy, z); incdec_op(&z_copy); if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); zval_ptr_dtor(&z_copy); zval_ptr_dtor(z); } else { @@ -20015,41 +15305,40 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t } } - zval_ptr_dtor_nogc(free_op2); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_post_incdec_property_helper_SPEC_VAR_TMP(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_post_incdec_property_helper_SPEC_VAR_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_post_incdec_property_helper_SPEC_VAR_TMP(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_post_incdec_property_helper_SPEC_VAR_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -20059,8 +15348,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20069,10 +15358,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -20082,8 +15371,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } ZVAL_DEREF(container); - zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20092,26 +15381,26 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); @@ -20124,29 +15413,29 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } else { - if (IS_TMP_VAR == IS_UNUSED) { + if (IS_CONST == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -20156,8 +15445,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } ZVAL_DEREF(container); - zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20166,17 +15455,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *container; - zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -20187,7 +15476,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND /* here we are sure we are dealing with an object */ do { - if (IS_TMP_VAR == IS_CONST && + if (IS_CONST == IS_CONST && EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); zend_object *zobj = Z_OBJ_P(container); @@ -20207,7 +15496,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND } } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); if (retval != EX_VAR(opline->result.var)) { ZVAL_COPY(EX_VAR(opline->result.var), retval); @@ -20215,29 +15504,28 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND } while (0); } - zval_ptr_dtor_nogc(free_op2); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *property; zval *container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20246,22 +15534,22 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *property; zval *container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20270,17 +15558,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *container; - zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -20290,7 +15578,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN /* here we are sure we are dealing with an object */ do { - if (IS_TMP_VAR == IS_CONST && + if (IS_CONST == IS_CONST && EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); zend_object *zobj = Z_OBJ_P(container); @@ -20310,7 +15598,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN } } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); if (retval != EX_VAR(opline->result.var)) { ZVAL_COPY(EX_VAR(opline->result.var), retval); @@ -20318,24 +15606,23 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN } while (0); } - zval_ptr_dtor_nogc(free_op2); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *property; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { @@ -20344,8 +15631,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20353,25 +15640,25 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container, *property; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20380,22 +15667,55 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + + zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + ZVAL_COPY(EX_VAR(opline->result.var), value); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) && + EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) { + zval *result = EX_VAR(opline->result.var); + zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, opline->op2.zv, BP_VAR_R, result TSRMLS_CC); + + if (retval) { + if (result != retval) { + ZVAL_COPY(result, retval); + } + } else { + ZVAL_NULL(result); + } + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; zval *object; zval *property_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property_name = opline->op2.zv; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); @@ -20403,7 +15723,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -20417,28 +15737,28 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL } ZVAL_DEREF(object_ptr); if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - zend_free_op free_op2; - zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zval *property_name = opline->op2.zv; + + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + } else { - zend_free_op free_op2, free_op_data1; + zend_free_op free_op_data1; zval rv; zval *value; - zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zval *dim = opline->op2.zv; zval *variable_ptr; if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); variable_ptr = Z_INDIRECT(rv); @@ -20465,26 +15785,26 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *value; zval *variable_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + value = opline->op2.zv; variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_VAR == IS_TMP_VAR) { - zval_ptr_dtor_nogc(free_op2); + if (IS_CONST == IS_TMP_VAR) { + } if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR TSRMLS_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST TSRMLS_CC); if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -20497,11 +15817,11 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -20509,9 +15829,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE SAVE_OPLINE(); - function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + function_name = opline->op2.zv; - if (IS_TMP_VAR != IS_CONST && + if (IS_CONST != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -20525,12 +15845,12 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); if (EG(exception) != NULL) { @@ -20569,7 +15889,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE obj = Z_OBJ_P(object); called_scope = obj->ce; - if (IS_TMP_VAR != IS_CONST || + if (IS_CONST != IS_CONST || EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; @@ -20578,11 +15898,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE } /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } - if (IS_TMP_VAR == IS_CONST && + if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && EXPECTED(obj == orig_obj)) { @@ -20599,14 +15919,13 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -20635,18 +15954,18 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND } if (IS_VAR == IS_CONST && - IS_TMP_VAR == IS_CONST && + IS_CONST == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else if (IS_VAR != IS_CONST && - IS_TMP_VAR == IS_CONST && + IS_CONST == IS_CONST && (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) { /* do nothing */ - } else if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; + } else if (IS_CONST != IS_UNUSED) { - function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - if (IS_TMP_VAR != IS_CONST) { + + function_name = opline->op2.zv; + if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -20658,12 +15977,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND if (ce->get_static_method) { fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC); } else { - fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); } if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); } - if (IS_TMP_VAR == IS_CONST && + if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { @@ -20672,8 +15991,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc); } } - if (IS_TMP_VAR != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + if (IS_CONST != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -20722,7 +16041,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); - if (IS_TMP_VAR == IS_UNUSED) { + if (IS_CONST == IS_UNUSED) { EX(call)->return_value = NULL; } @@ -20730,23 +16049,105 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + if (IS_VAR == IS_UNUSED) { + zend_constant *c; + zval *retval; - zval_ptr_dtor_nogc(free_op2); + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + c = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else if ((c = zend_quick_get_constant(opline->op2.zv + 1, opline->extended_value TSRMLS_CC)) == NULL) { + if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { + char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); + if (!actual) { + ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(opline->op2.zv))); + } else { + actual++; + ZVAL_STRINGL(EX_VAR(opline->result.var), + actual, Z_STRLEN_P(opline->op2.zv) - (actual - Z_STRVAL_P(opline->op2.zv))); + } + /* non-qualified constant - allow text substitution */ + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", + Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv)); + } + } else { + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), c); + } + retval = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(retval, &c->value); + if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) { + if (Z_OPT_COPYABLE_P(retval)) { + zval_copy_ctor_func(retval); + } else { + Z_ADDREF_P(retval); + } + } + } else { + /* class constant */ + zend_class_entry *ce; + zval *value; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + value = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + ZVAL_DEREF(value); + ZVAL_DUP(EX_VAR(opline->result.var), value); + goto constant_fetch_end; + } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce)) != NULL) { + ZVAL_DEREF(value); + ZVAL_DUP(EX_VAR(opline->result.var), value); + goto constant_fetch_end; + } + } + + if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) { + ZVAL_DEREF(value); + if (Z_CONSTANT_P(value)) { + EG(scope) = ce; + zval_update_constant(value, 1 TSRMLS_CC); + EG(scope) = EX(func)->op_array.scope; + } + if (IS_VAR == IS_CONST) { + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), value); + } else { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce, value); + } + ZVAL_DUP(EX_VAR(opline->result.var), value); + } else if (Z_STRLEN_P(opline->op2.zv) == sizeof("class")-1 && memcmp(Z_STRVAL_P(opline->op2.zv), "class", sizeof("class") - 1) == 0) { + /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ + ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + } else { + zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv)); + } + } +constant_fetch_end: CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -20781,9 +16182,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD } } - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + if (IS_CONST != IS_UNUSED) { + + zval *offset = opline->op2.zv; zend_string *str; zend_ulong hval; @@ -20799,7 +16200,7 @@ num_index: break; case IS_STRING: str = Z_STR_P(offset); - if (IS_TMP_VAR != IS_CONST) { + if (IS_CONST != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index; } @@ -20826,7 +16227,7 @@ str_index: /* do nothing */ break; } - zval_ptr_dtor_nogc(free_op2); + } else { zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } @@ -20834,7 +16235,7 @@ str_index: ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -20860,15 +16261,15 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); #if 0 || IS_VAR != IS_UNUSED } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #endif } } -static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; zval *offset; zend_ulong hval; @@ -20882,7 +16283,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE ZVAL_DEREF(container); } SEPARATE_ZVAL_NOREF(container); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); @@ -20898,7 +16299,7 @@ num_index_dim: zend_hash_index_del(ht, hval); break; case IS_STRING: - if (IS_TMP_VAR != IS_CONST) { + if (IS_CONST != IS_CONST) { if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { goto num_index_dim; } @@ -20929,31 +16330,31 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - zval_ptr_dtor_nogc(free_op2); + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use object as array"); } -//??? if (IS_TMP_VAR == IS_CONST) { +//??? if (IS_CONST == IS_CONST) { //??? zval_copy_ctor(offset); //??? } Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ } else { - zval_ptr_dtor_nogc(free_op2); + } if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; zval *offset; @@ -20962,28 +16363,28 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if (IS_VAR != IS_UNUSED) { ZVAL_DEREF(container); } if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to unset property of non-object"); } } - zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; int result; zend_ulong hval; @@ -20991,7 +16392,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_O SAVE_OPLINE(); container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); @@ -21001,7 +16402,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_O isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_TMP_VAR != IS_CONST) { + if (IS_CONST != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index_prop; } @@ -21061,7 +16462,7 @@ num_index_prop: result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + if (IS_CONST & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -21087,28 +16488,27 @@ num_index_prop: result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_ptr_dtor_nogc(free_op2); ZVAL_BOOL(EX_VAR(opline->result.var), result); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container; int result; zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); result = 0; @@ -21120,14 +16520,52 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_ result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_ptr_dtor_nogc(free_op2); ZVAL_BOOL(EX_VAR(opline->result.var), result); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -21209,21 +16647,21 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR } /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { + if (IS_CONST == IS_CONST) { ZVAL_DUP(&generator->key, key); - } else if (IS_TMP_VAR == IS_TMP_VAR) { + } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { + } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { + if (IS_CONST == IS_CV) { if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); } } @@ -21259,27 +16697,27 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_POW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; SAVE_OPLINE(); pow_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + opline->op2.zv TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_binary_assign_op_helper_SPEC_VAR_TMP(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_CONST(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21287,14 +16725,14 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mod_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21302,14 +16740,14 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21317,14 +16755,14 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21332,14 +16770,14 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); concat_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21347,14 +16785,14 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); fast_is_identical_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21363,14 +16801,14 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE SAVE_OPLINE(); fast_is_not_identical_function(result, _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21378,14 +16816,14 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_or_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21393,14 +16831,14 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_and_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21408,14 +16846,14 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21423,19 +16861,19 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); boolean_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2, free_op_data1; zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); zval *value; zval *zptr; @@ -21461,7 +16899,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); SEPARATE_ZVAL_NOREF(zptr); @@ -21476,7 +16914,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin if (opline->extended_value == ZEND_ASSIGN_OBJ) { if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); } } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { if (Z_OBJ_HT_P(object)->read_dimension) { @@ -21497,7 +16935,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin SEPARATE_ZVAL_IF_NOT_REF(z); binary_op(z, z, value TSRMLS_CC); if (opline->extended_value == ZEND_ASSIGN_OBJ) { - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } @@ -21524,7 +16962,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2, free_op_data1; @@ -21543,11 +16981,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin if (IS_VAR == IS_VAR && !(free_op1 != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); var_ptr = Z_INDIRECT(rv); @@ -21580,7 +17018,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -21588,7 +17026,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -21616,1778 +17054,1301 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_VAR_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *object; - zval *property; - zval *retval; - zval *zptr; + zval *container; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - retval = EX_VAR(opline->result.var); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } +static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; - if (IS_VAR != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - /* here we are sure we are dealing with an object */ - - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } else { - zval rv; - - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); +static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - incdec_op(z); - ZVAL_COPY_VALUE(retval, z); - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - SELECTIVE_PZVAL_LOCK(retval, opline); - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); - } - } + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - + ZVAL_DEREF(container); + zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_pre_incdec_property_helper_SPEC_VAR_VAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; -static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_VAR_VAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *container; zend_free_op free_op1, free_op2; - zval *object; - zval *property; - zval *retval; - zval *zptr; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - retval = EX_VAR(opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + if (IS_TMP_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_VAR != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } +static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); - ZVAL_NULL(retval); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(container); + zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - /* here we are sure we are dealing with an object */ +static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - ZVAL_DEREF(zptr); - ZVAL_COPY_VALUE(retval, zptr); - zval_opt_copy_ctor(zptr); + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - incdec_op(zptr); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); } else { - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval rv; - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - zval z_copy; - - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + zend_free_op free_op2, free_op_data1; + zval rv; + zval *value; + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zval *variable_ptr; - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); + } else { + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + FREE_OP(free_op_data1); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } - ZVAL_COPY_VALUE(z, value); } - ZVAL_DUP(retval, z); - ZVAL_DUP(&z_copy, z); - incdec_op(&z_copy); - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - zval_ptr_dtor(&z_copy); - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - ZVAL_NULL(retval); } } - - zval_ptr_dtor_nogc(free_op2); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_post_incdec_property_helper_SPEC_VAR_VAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *value; + zval *variable_ptr; -static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_post_incdec_property_helper_SPEC_VAR_VAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_VAR == IS_TMP_VAR) { + zval_ptr_dtor_nogc(free_op2); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *varname; - zval *retval; - zend_string *name; - HashTable *target_symbol_table; - SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + /* The generator object is stored in EX(return_value) */ + zend_generator *generator = (zend_generator *) EX(return_value); - if (IS_VAR == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - zend_string_addref(name); - } else { - name = zval_get_string(varname); + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); } + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ if (IS_VAR != IS_UNUSED) { - zend_class_entry *ce; + zend_free_op free_op1; - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + ZVAL_COPY_VALUE(&generator->value, value); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + + /* Temporary variables don't need ctor copying */ + if (IS_VAR != IS_TMP_VAR) { + zval_opt_copy_ctor(&generator->value); + } } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - if (IS_VAR != IS_CONST) { - zend_string_release(name); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - retval = zend_std_get_static_property(ce, name, 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - retval = zend_hash_find(target_symbol_table, name); - if (retval == NULL) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); - break; - EMPTY_SWITCH_DEFAULT_CASE() + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + } else { + ZVAL_MAKE_REF(value_ptr); } - } - } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1 TSRMLS_CC); - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - zval_ptr_dtor_nogc(free_op1); - } - } + ZVAL_COPY(&generator->value, value_ptr); - if (IS_VAR != IS_CONST) { - zend_string_release(name); - } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { - ZVAL_UNREF(retval); + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_DUP(&generator->value, value); + } else if (IS_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) { + ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(free_op1); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } } - ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} -static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); -static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_DUP(&generator->key, key); + } else if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->key, key); + } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { + ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); -static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + } else { + ZVAL_COPY_VALUE(&generator->key, key); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + } + } -static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); } else { - return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + generator->send_target = NULL; } -} -static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); -static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + pow_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + return zend_binary_assign_op_helper_SPEC_VAR_TMP(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + fast_mod_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + shift_left_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zend_free_op free_op1, free_op2; SAVE_OPLINE(); - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - zval_ptr_dtor_nogc(free_op2); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } else { - if (IS_VAR == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); - } + shift_right_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + concat_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *container; - zend_free_op free_op2; - zval *offset; + zend_free_op free_op1, free_op2; SAVE_OPLINE(); - container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); - } - - zval_ptr_dtor_nogc(free_op2); + fast_is_identical_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *property; - zval *container; + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + fast_is_not_identical_function(result, + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *property; - zval *container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); + bitwise_or_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *container; - zend_free_op free_op2; - zval *offset; + zend_free_op free_op1, free_op2; SAVE_OPLINE(); - container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); - } - - zval_ptr_dtor_nogc(free_op2); + bitwise_and_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1, free_op2; - zval *property; - - SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } else { - return ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *container, *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + bitwise_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); - if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *object; - zval *property_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + boolean_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op2); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *object_ptr; + zend_free_op free_op1, free_op2, free_op_data1; + zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zval *value; + zval *zptr; - SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } - if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); } - ZVAL_DEREF(object_ptr); - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - zend_free_op free_op2; - zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } } else { - zend_free_op free_op2, free_op_data1; - zval rv; - zval *value; - zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); - zval *variable_ptr; + /* here we are sure we are dealing with an object */ + if (opline->extended_value == ZEND_ASSIGN_OBJ + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && - EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - FREE_OP(free_op_data1); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } } else { - zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - variable_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); + zval *z = NULL; + zval rv; + + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv TSRMLS_CC); + } + } + if (z) { + if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + } + ZVAL_COPY_VALUE(z, value); + } +//??? if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + SEPARATE_ZVAL_IF_NOT_REF(z); + binary_op(z, z, value TSRMLS_CC); + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); + } if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_COPY(EX_VAR(opline->result.var), z); } + zval_ptr_dtor(z); } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); - if ((opline+1)->op1_type == IS_VAR) { - FREE_OP(free_op_data1); - } + zend_error(E_WARNING, "Attempt to assign property of non-object"); if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_NULL(EX_VAR(opline->result.var)); } } } + + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - /* assign_dim has two opcodes! */ + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *value; - zval *variable_ptr; + zend_free_op free_op1, free_op2, free_op_data1; + zval *var_ptr, rv; + zval *value, *container; SAVE_OPLINE(); - value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_VAR == IS_TMP_VAR) { - zval_ptr_dtor_nogc(free_op2); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_VAR == IS_VAR && !(free_op1 != NULL)) { + Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } - if (RETURN_VALUE_USED(opline)) { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + + zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); + } + + if (UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + } + + if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, IS_VAR TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + binary_op(var_ptr, var_ptr, value TSRMLS_CC); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } - /* zend_assign_to_variable() always takes care of op2, never free it! */ - zval_ptr_dtor_nogc(free_op2); - + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *variable_ptr; - zval *value_ptr; + zval *var_ptr; + zval *value; SAVE_OPLINE(); - value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } - if (IS_VAR == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!(free_op2 != NULL)) { - PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ - } - zend_error(E_STRICT, "Only variables should be assigned by reference"); - if (UNEXPECTED(EG(exception) != NULL)) { - if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; - HANDLE_EXCEPTION(); - } - return ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { - if (!(free_op2 != NULL)) { - PZVAL_LOCK(value_ptr); - } + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } - if (IS_VAR == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); - } - if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || - (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { - variable_ptr = &EG(uninitialized_zval); + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr TSRMLS_CC); - } + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); - if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { - if (!(free_op2 != NULL)) { - Z_DELREF_P(variable_ptr); - } - } + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } + zval_ptr_dtor_nogc(free_op2); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; - zend_free_op free_op1, free_op2; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; - - SAVE_OPLINE(); - - function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_VAR != IS_CONST && - UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); - } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - obj = Z_OBJ_P(object); - called_scope = obj->ce; - - if (IS_VAR != IS_CONST || - EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { - zend_object *orig_obj = obj; - - if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); - } - - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_VAR == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(obj == orig_obj)) { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); - } - } +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; - } else { - GC_REFCOUNT(obj)++; /* For $this pointer */ + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; - zend_class_entry *ce; - zend_object *object; - zend_function *fbc; - - SAVE_OPLINE(); - if (IS_VAR == IS_CONST) { - /* no function found. try a static method in class */ - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - if (IS_VAR == IS_CONST && - IS_VAR == IS_CONST && - CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else if (IS_VAR != IS_CONST && - IS_VAR == IS_CONST && - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) { - /* do nothing */ - } else if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - - function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_VAR != IS_CONST) { - if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Function name must be a string"); - } - } +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (ce->get_static_method) { - fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC); - } else { - fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - } - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_VAR == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { - if (IS_VAR == IS_CONST) { - CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc); - } else { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc); - } - } - if (IS_VAR != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); - } - } else { - if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); - } - if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); - } - fbc = ce->constructor; + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - object = NULL; - if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_OBJ(EX(This))) { - object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; - } - if (!object || - !instanceof_function(object->ce, ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); - } - } - } +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (IS_VAR != IS_CONST) { - /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { - ce = EX(called_scope); - } + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (IS_VAR == IS_UNUSED) { - EX(call)->return_value = NULL; + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *expr_ptr, new_expr; - SAVE_OPLINE(); - if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); - } - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } else if (IS_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } - } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) { - expr_ptr = Z_REFVAL_P(expr_ptr); - if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); - zval_ptr_dtor_nogc(free_op1); - } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - zend_string *str; - zend_ulong hval; +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE -add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; - } - zval_ptr_dtor_nogc(free_op2); - } else { - zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_VAR_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} + +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; - array = EX_VAR(opline->result.var); - if (IS_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_NEW_ARR(array); - zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR != IS_UNUSED) { - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init(Z_ARRVAL_P(array), 0); - } + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (IS_VAR == IS_UNUSED) { - ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_VAR != IS_UNUSED - } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#endif + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval tmp, *varname; - HashTable *target_symbol_table; - zend_free_op free_op1; + zend_free_op free_op1, free_op2; + zval *container; SAVE_OPLINE(); - if (IS_VAR == IS_CV && - IS_VAR == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - zval *var = EX_VAR(opline->op1.var); - - if (Z_REFCOUNTED_P(var)) { - zend_refcounted *garbage = Z_COUNTED_P(var); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (!--GC_REFCOUNT(garbage)) { - ZVAL_UNDEF(var); - _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); - } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); - } - } else { - ZVAL_UNDEF(var); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; + ZVAL_DEREF(container); + zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_VAR != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); - } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; - if (IS_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; - zval *offset; - zend_ulong hval; + zend_free_op free_op1, free_op2; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - if (IS_VAR != IS_UNUSED) { - ZVAL_DEREF(container); - } - SEPARATE_ZVAL_NOREF(container); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); -offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); - } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zval_ptr_dtor_nogc(free_op2); - } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } -//??? if (IS_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } else { + if (IS_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); } - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; zval *container; - zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_VAR != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->unset_property) { - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to unset property of non-object"); - } + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); + zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; + zend_free_op free_op1; + zval *object_ptr; SAVE_OPLINE(); - if (IS_VAR == IS_CV && - IS_VAR == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - value = EX_VAR(opline->op1.var); - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !i_zend_is_true(value TSRMLS_CC)); - CHECK_EXCEPTION(); - } - ZEND_VM_NEXT_OPCODE(); - } else { - zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - ZVAL_UNDEF(&tmp); - if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_VAR != IS_UNUSED) { - zend_class_entry *ce; + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + } else { + zend_free_op free_op2, free_op_data1; + zval rv; + zval *value; + zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + zval *variable_ptr; - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); + } else { + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + FREE_OP(free_op_data1); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); + value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } - value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - value && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !value || !i_zend_is_true(value TSRMLS_CC)); } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *container; - int result; - zend_ulong hval; - zval *offset; + zval *value; + zval *variable_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); - zval *value; - zend_string *str; - -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } - } -str_index_prop: - value = zend_hash_find_ind(ht, str); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - value = NULL; - break; - } - } - - if (opline->extended_value & ZEND_ISSET) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); - } - } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { - result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check element of non-array"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ - zval tmp; + value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - result = 0; - if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(offset); - } - if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ - || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ - && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { - ZVAL_DUP(&tmp, offset); - convert_to_long(&tmp); - offset = &tmp; - } - } - if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { - if ((opline->extended_value & ZEND_ISSET) || - Z_STRVAL_P(container)[offset->value.lval] != '0') { - result = 1; - } - } + if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_VAR == IS_TMP_VAR) { + zval_ptr_dtor_nogc(free_op2); } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_ptr_dtor_nogc(free_op1); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *container; - int result; - zval *offset; + zval *variable_ptr; + zval *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + if (!(free_op2 != NULL)) { + PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; + zend_error(E_STRICT, "Only variables should be assigned by reference"); + if (UNEXPECTED(EG(exception) != NULL)) { + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + HANDLE_EXCEPTION(); + } + return ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { + if (!(free_op2 != NULL)) { + PZVAL_LOCK(value_ptr); } + } + + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } + if (IS_VAR == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(variable_ptr))) { + zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); + } + if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || + (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { + variable_ptr = &EG(uninitialized_zval); } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + zend_assign_to_variable_reference(variable_ptr, value_ptr TSRMLS_CC); } - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_ptr_dtor_nogc(free_op1); + if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { + if (!(free_op2 != NULL)) { + Z_DELREF_P(variable_ptr); + } + } + + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -23909,154 +18870,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE } } -static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *varname; - zval *retval; - zend_string *name; - HashTable *target_symbol_table; - - SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - zend_string_addref(name); - } else { - name = zval_get_string(varname); - } - - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - if (IS_VAR != IS_CONST) { - zend_string_release(name); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - retval = zend_std_get_static_property(ce, name, 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - retval = zend_hash_find(target_symbol_table, name); - if (retval == NULL) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1 TSRMLS_CC); - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - zval_ptr_dtor_nogc(free_op1); - } - } - - if (IS_VAR != IS_CONST) { - zend_string_release(name); - } - - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { - ZVAL_UNREF(retval); - } - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -24444,153 +19257,6 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA } } -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval tmp, *varname; - HashTable *target_symbol_table; - zend_free_op free_op1; - - SAVE_OPLINE(); - if (IS_VAR == IS_CV && - IS_UNUSED == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - zval *var = EX_VAR(opline->op1.var); - - if (Z_REFCOUNTED_P(var)) { - zend_refcounted *garbage = Z_COUNTED_P(var); - - if (!--GC_REFCOUNT(garbage)) { - ZVAL_UNDEF(var); - _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); - } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); - } - } else { - ZVAL_UNDEF(var); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - - SAVE_OPLINE(); - if (IS_VAR == IS_CV && - IS_UNUSED == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - value = EX_VAR(opline->op1.var); - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !i_zend_is_true(value TSRMLS_CC)); - CHECK_EXCEPTION(); - } - ZEND_VM_NEXT_OPCODE(); - } else { - zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - - ZVAL_UNDEF(&tmp); - if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); - } - - if (IS_VAR != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - zval_ptr_dtor_nogc(free_op1); - - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - value && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !value || !i_zend_is_true(value TSRMLS_CC)); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } -} - static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -26157,21 +20823,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -26487,7 +21138,7 @@ num_index_prop: result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_CV == IS_CV || IS_CV == IS_VAR) { + if (IS_CV & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -26703,440 +21354,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE return zend_binary_assign_op_helper_SPEC_VAR_CV(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *obj; - zend_class_entry *ce; - zend_function *clone; - zend_object_clone_obj_t clone_call; - - SAVE_OPLINE(); - obj = _get_obj_zval_ptr_unused(execute_data); - - if (IS_UNUSED == IS_CONST || - (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "__clone method called on non-object"); - } - - ce = Z_OBJCE_P(obj); - clone = ce ? ce->clone : NULL; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; - if (UNEXPECTED(clone_call == NULL)) { - if (ce) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); - } else { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); - } - } - - if (ce && clone) { - if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); - } - } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); - } - } - } - - if (EXPECTED(EG(exception) == NULL)) { - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj TSRMLS_CC)); - if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var))); - } - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_EXIT_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 || (IS_UNUSED != IS_UNUSED) - USE_OPLINE - - SAVE_OPLINE(); - if (IS_UNUSED != IS_UNUSED) { - - zval *ptr = NULL; - - if (Z_TYPE_P(ptr) == IS_LONG) { - EG(exit_status) = Z_LVAL_P(ptr); - } else { - zend_print_variable(ptr TSRMLS_CC); - } - - } -#endif - zend_bailout(); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ -} - -static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data1; - zval *object = _get_obj_zval_ptr_unused(execute_data); - zval *property = opline->op2.zv; - zval *value; - zval *zptr; - - if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - - if (IS_UNUSED != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); - } - - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - - FREE_OP(free_op_data1); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - /* here we are sure we are dealing with an object */ - if (opline->extended_value == ZEND_ASSIGN_OBJ - && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } else { - zval *z = NULL; - zval rv; - - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - } - } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv TSRMLS_CC); - } - } - if (z) { - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } -//??? if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - binary_op(z, z, value TSRMLS_CC); - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), z); - } - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } - } - - FREE_OP(free_op_data1); - } - - /* assign_obj has two opcodes! */ - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op_data1; - zval *var_ptr, rv; - zval *value, *container; - - SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - if (IS_UNUSED != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_UNUSED == IS_VAR && !0) { - Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ - } - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zval *dim = opline->op2.zv; - - zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - } - - if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } - - if (UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - binary_op(var_ptr, var_ptr, value TSRMLS_CC); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - } - - FREE_OP(free_op_data1); - - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *var_ptr; - zval *value; - - SAVE_OPLINE(); - value = opline->op2.zv; - var_ptr = NULL; - - if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } - - if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - binary_op(var_ptr, var_ptr, value TSRMLS_CC); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - } - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - + zend_free_op free_op1, free_op2; zval *object; zval *property; zval *retval; zval *zptr; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(execute_data); - property = opline->op2.zv; + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); retval = EX_VAR(opline->result.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (IS_UNUSED != IS_UNUSED) { + if (IS_VAR != IS_UNUSED) { object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ } - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - + zval_ptr_dtor_nogc(free_op2); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(retval); } - + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -27144,7 +21390,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde /* here we are sure we are dealing with an object */ if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); SEPARATE_ZVAL_NOREF(zptr); @@ -27157,7 +21403,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { zval rv; @@ -27172,7 +21418,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde SEPARATE_ZVAL_IF_NOT_REF(z); incdec_op(z); ZVAL_COPY_VALUE(retval, z); - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); SELECTIVE_PZVAL_LOCK(retval, opline); zval_ptr_dtor(z); } else { @@ -27183,48 +21429,49 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde } } - + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op1, free_op2; zval *object; zval *property; zval *retval; zval *zptr; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(execute_data); - property = opline->op2.zv; + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); retval = EX_VAR(opline->result.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (IS_UNUSED != IS_UNUSED) { + if (IS_VAR != IS_UNUSED) { object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ } - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - + zval_ptr_dtor_nogc(free_op2); ZVAL_NULL(retval); - + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -27232,7 +21479,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd /* here we are sure we are dealing with an object */ if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); ZVAL_COPY_VALUE(retval, zptr); @@ -27242,7 +21489,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); zval z_copy; if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { @@ -27258,7 +21505,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd ZVAL_DUP(&z_copy, z); incdec_op(&z_copy); if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); zval_ptr_dtor(&z_copy); zval_ptr_dtor(z); } else { @@ -27267,34 +21514,35 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd } } - + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op1; zval *container; - + zend_free_op free_op2; zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - offset = opline->op2.zv; + container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -27303,7 +21551,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE /* here we are sure we are dealing with an object */ do { - if (IS_CONST == IS_CONST && + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); zend_object *zobj = Z_OBJ_P(container); @@ -27323,7 +21571,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE } } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); if (retval != EX_VAR(opline->result.var)) { ZVAL_COPY(EX_VAR(opline->result.var), retval); @@ -27331,73 +21579,74 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE } while (0); } - + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval *property; zval *container; SAVE_OPLINE(); - property = opline->op2.zv; + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - - if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval *property; zval *container; SAVE_OPLINE(); - property = opline->op2.zv; - container = _get_obj_zval_ptr_unused(execute_data); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); - - if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op1; zval *container; - + zend_free_op free_op2; zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - offset = opline->op2.zv; + container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -27405,7 +21654,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD /* here we are sure we are dealing with an object */ do { - if (IS_CONST == IS_CONST && + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); zend_object *zobj = Z_OBJ_P(container); @@ -27425,7 +21674,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD } } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); if (retval != EX_VAR(opline->result.var)) { ZVAL_COPY(EX_VAR(opline->result.var), retval); @@ -27433,133 +21682,96 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD } while (0); } - + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval *property; SAVE_OPLINE(); - property = opline->op2.zv; - container = _get_obj_zval_ptr_unused(execute_data); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - - if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval *container, *property; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - property = opline->op2.zv; + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); - - if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op1, free_op2; zval *object; zval *property_name; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(execute_data); - property_name = opline->op2.zv; + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - - + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *str = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - - if (IS_UNUSED == IS_UNUSED) { - /* Initialize for erealloc in add_char_to_string */ - ZVAL_EMPTY_STRING(str); - } - - add_char_to_string(str, str, opline->op2.zv); - - /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */ - /*CHECK_EXCEPTION();*/ - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ADD_STRING_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *str = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - - if (IS_UNUSED == IS_UNUSED) { - /* Initialize for erealloc in add_string_to_string */ - ZVAL_EMPTY_STRING(str); - } - - add_string_to_string(str, str, opline->op2.zv); - - /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */ - /*CHECK_EXCEPTION();*/ - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; - + zend_free_op free_op1, free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -27567,9 +21779,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O SAVE_OPLINE(); - function_name = opline->op2.zv; + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_CONST != IS_CONST && + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -27577,18 +21789,19 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O zend_error_noreturn(E_ERROR, "Method name must be a string"); } - object = _get_obj_zval_ptr_unused(execute_data); + object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { - + zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); } zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); if (EG(exception) != NULL) { HANDLE_EXCEPTION(); @@ -27626,7 +21839,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O obj = Z_OBJ_P(object); called_scope = obj->ce; - if (IS_CONST != IS_CONST || + if ((IS_TMP_VAR|IS_VAR) != IS_CONST || EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; @@ -27635,11 +21848,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O } /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } - if (IS_CONST == IS_CONST && + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && EXPECTED(obj == orig_obj)) { @@ -27656,117 +21869,233 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *function_name; + zend_class_entry *ce; + zend_object *object; + zend_function *fbc; SAVE_OPLINE(); - if (IS_UNUSED == IS_UNUSED) { - zend_constant *c; - zval *retval; - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - c = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else if ((c = zend_quick_get_constant(opline->op2.zv + 1, opline->extended_value TSRMLS_CC)) == NULL) { - if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { - char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); - if (!actual) { - ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(opline->op2.zv))); - } else { - actual++; - ZVAL_STRINGL(EX_VAR(opline->result.var), - actual, Z_STRLEN_P(opline->op2.zv) - (actual - Z_STRVAL_P(opline->op2.zv))); - } - /* non-qualified constant - allow text substitution */ - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", - Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } else { - zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv)); - } + if (IS_VAR == IS_CONST) { + /* no function found. try a static method in class */ + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); } else { - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), c); - } - retval = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(retval, &c->value); - if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) { - if (Z_OPT_COPYABLE_P(retval)) { - zval_copy_ctor_func(retval); - } else { - Z_ADDREF_P(retval); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); } } else { - /* class constant */ - zend_class_entry *ce; - zval *value; + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - value = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - goto constant_fetch_end; - } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); + if (IS_VAR == IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && + CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else if (IS_VAR != IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && + (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) { + /* do nothing */ + } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zend_free_op free_op2; + + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); - } + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC); } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce)) != NULL) { - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - goto constant_fetch_end; + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + } + if (UNEXPECTED(fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + if (IS_VAR == IS_CONST) { + CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc); + } else { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc); } } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(free_op2); + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot call constructor"); + } + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + } + fbc = ce->constructor; + } - if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) { - ZVAL_DEREF(value); - if (Z_CONSTANT_P(value)) { - EG(scope) = ce; - zval_update_constant(value, 1 TSRMLS_CC); - EG(scope) = EX(func)->op_array.scope; - } - if (IS_UNUSED == IS_CONST) { - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), value); + object = NULL; + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); + GC_REFCOUNT(object)++; + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } else { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce, value); + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } - ZVAL_DUP(EX_VAR(opline->result.var), value); - } else if (Z_STRLEN_P(opline->op2.zv) == sizeof("class")-1 && memcmp(Z_STRVAL_P(opline->op2.zv), "class", sizeof("class") - 1) == 0) { - /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ - ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); - } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv)); } } -constant_fetch_end: + + if (IS_VAR != IS_CONST) { + /* previous opcode is ZEND_FETCH_CLASS */ + if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) { + ce = EX(called_scope); + } + } + + EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + EX(call)->return_value = NULL; + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && + (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + } + ZVAL_MAKE_REF(expr_ptr); + Z_ADDREF_P(expr_ptr); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } else if (IS_VAR == IS_CONST) { + if (!Z_IMMUTABLE_P(expr_ptr)) { + ZVAL_DUP(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } + } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) { + expr_ptr = Z_REFVAL_P(expr_ptr); + if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); + zval_ptr_dtor_nogc(free_op1); + } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zend_free_op free_op2; + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zend_string *str; + zend_ulong hval; + +add_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + break; + case IS_STRING: + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index; + case IS_FALSE: + hval = 0; + goto num_index; + case IS_TRUE: + hval = 1; + goto num_index; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto add_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); + /* do nothing */ + break; + } + zval_ptr_dtor_nogc(free_op2); + } else { + zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; USE_OPLINE array = EX_VAR(opline->result.var); - if (IS_UNUSED != IS_UNUSED) { + if (IS_VAR != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; } else { size = 0; @@ -27774,42 +22103,42 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_ ZVAL_NEW_ARR(array); zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); - if (IS_UNUSED != IS_UNUSED) { + if (IS_VAR != IS_UNUSED) { /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } } - if (IS_UNUSED == IS_UNUSED) { + if (IS_VAR == IS_UNUSED) { ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_UNUSED != IS_UNUSED +#if 0 || IS_VAR != IS_UNUSED } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #endif } } -static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op1, free_op2; zval *container; zval *offset; zend_ulong hval; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } - if (IS_UNUSED != IS_UNUSED) { + if (IS_VAR != IS_UNUSED) { ZVAL_DEREF(container); } SEPARATE_ZVAL_NOREF(container); - offset = opline->op2.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); offset_again: switch (Z_TYPE_P(offset)) { @@ -27823,7 +22152,7 @@ num_index_dim: zend_hash_index_del(ht, hval); break; case IS_STRING: - if (IS_CONST != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { goto num_index_dim; } @@ -27854,71 +22183,71 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - - } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zval_ptr_dtor_nogc(free_op2); + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use object as array"); } -//??? if (IS_CONST == IS_CONST) { +//??? if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { //??? zval_copy_ctor(offset); //??? } Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - + zval_ptr_dtor_nogc(free_op2); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ } else { - + zval_ptr_dtor_nogc(free_op2); } - + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op1, free_op2; zval *container; zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } - offset = opline->op2.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_UNUSED != IS_UNUSED) { + if (IS_VAR != IS_UNUSED) { ZVAL_DEREF(container); } - if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to unset property of non-object"); } } - - + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op1, free_op2; zval *container; int result; zend_ulong hval; zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - offset = opline->op2.zv; + container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -27926,7 +22255,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER(Z isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index_prop; } @@ -27971,7 +22300,7 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { @@ -27986,7 +22315,7 @@ num_index_prop: result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -28012,27 +22341,28 @@ num_index_prop: result = ((opline->extended_value & ZEND_ISSET) == 0); } + zval_ptr_dtor_nogc(free_op2); ZVAL_BOOL(EX_VAR(opline->result.var), result); - + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op1, free_op2; zval *container; int result; zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - offset = opline->op2.zv; + container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); result = 0; @@ -28044,154 +22374,99 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER( result = ((opline->extended_value & ZEND_ISSET) == 0); } + zval_ptr_dtor_nogc(free_op2); ZVAL_BOOL(EX_VAR(opline->result.var), result); - + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - /* The generator object is stored in EX(return_value) */ - zend_generator *generator = (zend_generator *) EX(return_value); - - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_UNUSED != IS_UNUSED) { - - - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = NULL; - ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_UNUSED != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); - } - } else { - zval *value_ptr = NULL; + zval *obj; + zend_class_entry *ce; + zend_function *clone; + zend_object_clone_obj_t clone_call; - if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); - } + SAVE_OPLINE(); + obj = _get_obj_zval_ptr_unused(execute_data); - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - } else { - ZVAL_MAKE_REF(value_ptr); - } - ZVAL_COPY(&generator->value, value_ptr); + if (IS_UNUSED == IS_CONST || + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "__clone method called on non-object"); + } - } + ce = Z_OBJCE_P(obj); + clone = ce ? ce->clone : NULL; + clone_call = Z_OBJ_HT_P(obj)->clone_obj; + if (UNEXPECTED(clone_call == NULL)) { + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); } else { - zval *value = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->value, value); - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); } - /* Set the new yielded key */ - if (IS_CONST != IS_UNUSED) { - - zval *key = opline->op2.zv; - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->key, key); - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + if (ce && clone) { + if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { + /* Ensure that if we're calling a private function, we're allowed to do so. + */ + if (UNEXPECTED(ce != EG(scope))) { + zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + } + } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { + /* Ensure that if we're calling a protected function, we're allowed to do so. + */ + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { + zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); } } + } - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); + if (EXPECTED(EG(exception) == NULL)) { + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj TSRMLS_CC)); + if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var))); } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); } - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); +static int ZEND_FASTCALL ZEND_EXIT_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 || (IS_UNUSED != IS_UNUSED) + USE_OPLINE - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ SAVE_OPLINE(); + if (IS_UNUSED != IS_UNUSED) { - ZEND_VM_RETURN(); -} + zval *ptr = NULL; -static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (Z_TYPE_P(ptr) == IS_LONG) { + EG(exit_status) = Z_LVAL_P(ptr); + } else { + zend_print_variable(ptr TSRMLS_CC); + } + + } +#endif + zend_bailout(); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } -static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data1; + zend_free_op free_op_data1; zval *object = _get_obj_zval_ptr_unused(execute_data); - zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zval *property = opline->op2.zv; zval *value; zval *zptr; @@ -28207,7 +22482,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); - zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -28217,7 +22492,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); SEPARATE_ZVAL_NOREF(zptr); @@ -28232,7 +22507,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* if (opline->extended_value == ZEND_ASSIGN_OBJ) { if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); } } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { if (Z_OBJ_HT_P(object)->read_dimension) { @@ -28253,7 +22528,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* SEPARATE_ZVAL_IF_NOT_REF(z); binary_op(z, z, value TSRMLS_CC); if (opline->extended_value == ZEND_ASSIGN_OBJ) { - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } @@ -28269,7 +22544,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* } } - zval_ptr_dtor_nogc(free_op2); FREE_OP(free_op_data1); } @@ -28279,10 +22553,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data1; + zend_free_op free_op_data1; zval *var_ptr, rv; zval *value, *container; @@ -28298,11 +22572,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (* if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zval *dim = opline->op2.zv; - zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); var_ptr = Z_INDIRECT(rv); @@ -28327,7 +22601,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (* } } - zval_ptr_dtor_nogc(free_op2); FREE_OP(free_op_data1); CHECK_EXCEPTION(); @@ -28335,15 +22608,15 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (* ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval *var_ptr; zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + value = opline->op2.zv; var_ptr = NULL; if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -28365,159 +22638,158 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina } } - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval *object; zval *property; zval *retval; @@ -28525,7 +22797,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; retval = EX_VAR(opline->result.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { @@ -28538,7 +22810,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); + if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(retval); } @@ -28550,7 +22822,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ /* here we are sure we are dealing with an object */ if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); SEPARATE_ZVAL_NOREF(zptr); @@ -28563,7 +22835,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { zval rv; @@ -28578,7 +22850,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ SEPARATE_ZVAL_IF_NOT_REF(z); incdec_op(z); ZVAL_COPY_VALUE(retval, z); - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); SELECTIVE_PZVAL_LOCK(retval, opline); zval_ptr_dtor(z); } else { @@ -28589,26 +22861,25 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ } } - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval *object; zval *property; zval *retval; @@ -28616,7 +22887,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; retval = EX_VAR(opline->result.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { @@ -28629,7 +22900,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); + ZVAL_NULL(retval); CHECK_EXCEPTION(); @@ -28639,7 +22910,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec /* here we are sure we are dealing with an object */ if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); ZVAL_COPY_VALUE(retval, zptr); @@ -28649,7 +22920,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); zval z_copy; if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { @@ -28665,7 +22936,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec ZVAL_DUP(&z_copy, z); incdec_op(&z_copy); if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); zval_ptr_dtor(&z_copy); zval_ptr_dtor(z); } else { @@ -28674,33 +22945,32 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec } } - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_post_incdec_property_helper_SPEC_UNUSED_TMP(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_post_incdec_property_helper_SPEC_UNUSED_TMP(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; - zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -28711,7 +22981,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H /* here we are sure we are dealing with an object */ do { - if (IS_TMP_VAR == IS_CONST && + if (IS_CONST == IS_CONST && EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); zend_object *zobj = Z_OBJ_P(container); @@ -28731,7 +23001,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H } } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); if (retval != EX_VAR(opline->result.var)) { ZVAL_COPY(EX_VAR(opline->result.var), retval); @@ -28739,29 +23009,28 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H } while (0); } - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *property; zval *container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -28770,22 +23039,22 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *property; zval *container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); + if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -28794,17 +23063,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; - zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -28814,7 +23083,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ /* here we are sure we are dealing with an object */ do { - if (IS_TMP_VAR == IS_CONST && + if (IS_CONST == IS_CONST && EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); zend_object *zobj = Z_OBJ_P(container); @@ -28834,7 +23103,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ } } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); if (retval != EX_VAR(opline->result.var)) { ZVAL_COPY(EX_VAR(opline->result.var), retval); @@ -28842,24 +23111,23 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ } while (0); } - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *property; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { @@ -28868,8 +23136,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -28877,25 +23145,25 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; + zend_free_op free_op1; zval *container, *property; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property = opline->op2.zv; if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -28904,22 +23172,22 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCO ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval *object; zval *property_name; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data); - property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + property_name = opline->op2.zv; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); @@ -28927,57 +23195,49 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *str = EX_VAR(opline->result.var); - zval *var; - zval var_copy; - int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); if (IS_UNUSED == IS_UNUSED) { - /* Initialize for erealloc in add_string_to_string */ + /* Initialize for erealloc in add_char_to_string */ ZVAL_EMPTY_STRING(str); } - if (Z_TYPE_P(var) != IS_STRING) { - if (IS_TMP_VAR != IS_TMP_VAR) { - ZVAL_DEREF(var); - } - if (Z_TYPE_P(var) != IS_STRING) { - use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); + add_char_to_string(str, str, opline->op2.zv); - if (use_copy) { - var = &var_copy; - } - } - } - add_string_to_string(str, str, var); + /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */ + /*CHECK_EXCEPTION();*/ + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_ADD_STRING_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *str = EX_VAR(opline->result.var); - if (use_copy) { - zend_string_release(Z_STR_P(var)); + SAVE_OPLINE(); + + if (IS_UNUSED == IS_UNUSED) { + /* Initialize for erealloc in add_string_to_string */ + ZVAL_EMPTY_STRING(str); } - /* original comment, possibly problematic: - * FREE_OP is missing intentionally here - we're always working on the same temporary variable - * (Zeev): I don't think it's problematic, we only use variables - * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're - * string offsets or overloaded objects - */ - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); + add_string_to_string(str, str, opline->op2.zv); + + /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */ + /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; - zend_free_op free_op2; + zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -28985,9 +23245,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC SAVE_OPLINE(); - function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + function_name = opline->op2.zv; - if (IS_TMP_VAR != IS_CONST && + if (IS_CONST != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -29001,12 +23261,12 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - zval_ptr_dtor_nogc(free_op2); + if (EG(exception) != NULL) { HANDLE_EXCEPTION(); @@ -29044,7 +23304,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC obj = Z_OBJ_P(object); called_scope = obj->ce; - if (IS_TMP_VAR != IS_CONST || + if (IS_CONST != IS_CONST || EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; @@ -29053,11 +23313,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC } /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } - if (IS_TMP_VAR == IS_CONST && + if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && EXPECTED(obj == orig_obj)) { @@ -29074,13 +23334,110 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (IS_UNUSED == IS_UNUSED) { + zend_constant *c; + zval *retval; + + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + c = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else if ((c = zend_quick_get_constant(opline->op2.zv + 1, opline->extended_value TSRMLS_CC)) == NULL) { + if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { + char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); + if (!actual) { + ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(opline->op2.zv))); + } else { + actual++; + ZVAL_STRINGL(EX_VAR(opline->result.var), + actual, Z_STRLEN_P(opline->op2.zv) - (actual - Z_STRVAL_P(opline->op2.zv))); + } + /* non-qualified constant - allow text substitution */ + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", + Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv)); + } + } else { + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), c); + } + retval = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(retval, &c->value); + if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) { + if (Z_OPT_COPYABLE_P(retval)) { + zval_copy_ctor_func(retval); + } else { + Z_ADDREF_P(retval); + } + } + } else { + /* class constant */ + zend_class_entry *ce; + zval *value; + + if (IS_UNUSED == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + value = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + ZVAL_DEREF(value); + ZVAL_DUP(EX_VAR(opline->result.var), value); + goto constant_fetch_end; + } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce)) != NULL) { + ZVAL_DEREF(value); + ZVAL_DUP(EX_VAR(opline->result.var), value); + goto constant_fetch_end; + } + } + + if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) { + ZVAL_DEREF(value); + if (Z_CONSTANT_P(value)) { + EG(scope) = ce; + zval_update_constant(value, 1 TSRMLS_CC); + EG(scope) = EX(func)->op_array.scope; + } + if (IS_UNUSED == IS_CONST) { + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), value); + } else { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce, value); + } + ZVAL_DUP(EX_VAR(opline->result.var), value); + } else if (Z_STRLEN_P(opline->op2.zv) == sizeof("class")-1 && memcmp(Z_STRVAL_P(opline->op2.zv), "class", sizeof("class") - 1) == 0) { + /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ + ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + } else { + zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv)); + } + } +constant_fetch_end: + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -29106,15 +23463,15 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); #if 0 || IS_UNUSED != IS_UNUSED } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #endif } } -static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval *container; zval *offset; zend_ulong hval; @@ -29128,7 +23485,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN ZVAL_DEREF(container); } SEPARATE_ZVAL_NOREF(container); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); @@ -29144,7 +23501,7 @@ num_index_dim: zend_hash_index_del(ht, hval); break; case IS_STRING: - if (IS_TMP_VAR != IS_CONST) { + if (IS_CONST != IS_CONST) { if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { goto num_index_dim; } @@ -29175,31 +23532,31 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - zval_ptr_dtor_nogc(free_op2); + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use object as array"); } -//??? if (IS_TMP_VAR == IS_CONST) { +//??? if (IS_CONST == IS_CONST) { //??? zval_copy_ctor(offset); //??? } Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ } else { - zval_ptr_dtor_nogc(free_op2); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval *container; zval *offset; @@ -29208,28 +23565,28 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if (IS_UNUSED != IS_UNUSED) { ZVAL_DEREF(container); } if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to unset property of non-object"); } } - zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval *container; int result; zend_ulong hval; @@ -29237,7 +23594,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEN SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); @@ -29247,7 +23604,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEN isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_TMP_VAR != IS_CONST) { + if (IS_CONST != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index_prop; } @@ -29307,7 +23664,7 @@ num_index_prop: result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + if (IS_CONST & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -29333,28 +23690,27 @@ num_index_prop: result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_ptr_dtor_nogc(free_op2); ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval *container; int result; zval *offset; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + offset = opline->op2.zv; if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); result = 0; @@ -29366,14 +23722,13 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMP_HANDLER(ZE result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_ptr_dtor_nogc(free_op2); ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -29454,21 +23809,21 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER } /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { + if (IS_CONST == IS_CONST) { ZVAL_DUP(&generator->key, key); - } else if (IS_TMP_VAR == IS_TMP_VAR) { + } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { + } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { + if (IS_CONST == IS_CV) { if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); } } @@ -29504,17 +23859,17 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2, free_op_data1; zval *object = _get_obj_zval_ptr_unused(execute_data); - zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); zval *value; zval *zptr; @@ -29540,7 +23895,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); SEPARATE_ZVAL_NOREF(zptr); @@ -29555,7 +23910,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* if (opline->extended_value == ZEND_ASSIGN_OBJ) { if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); } } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { if (Z_OBJ_HT_P(object)->read_dimension) { @@ -29576,7 +23931,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* SEPARATE_ZVAL_IF_NOT_REF(z); binary_op(z, z, value TSRMLS_CC); if (opline->extended_value == ZEND_ASSIGN_OBJ) { - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } @@ -29602,7 +23957,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2, free_op_data1; @@ -29621,11 +23976,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (* if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); var_ptr = Z_INDIRECT(rv); @@ -29658,7 +24013,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (* ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; @@ -29666,7 +24021,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); var_ptr = NULL; if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -29675,325 +24030,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - binary_op(var_ptr, var_ptr, value TSRMLS_CC); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - } - - zval_ptr_dtor_nogc(free_op2); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *object; - zval *property; - zval *retval; - zval *zptr; - - SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(execute_data); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - retval = EX_VAR(opline->result.var); - - if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (IS_UNUSED != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } - - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - /* here we are sure we are dealing with an object */ - - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } else { - zval rv; - - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - incdec_op(z); - ZVAL_COPY_VALUE(retval, z); - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - SELECTIVE_PZVAL_LOCK(retval, opline); - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); - } - } - } - - zval_ptr_dtor_nogc(free_op2); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *object; - zval *property; - zval *retval; - zval *zptr; - - SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(execute_data); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - retval = EX_VAR(opline->result.var); - - if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (IS_UNUSED != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } - - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); - ZVAL_NULL(retval); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - /* here we are sure we are dealing with an object */ - - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - - ZVAL_DEREF(zptr); - ZVAL_COPY_VALUE(retval, zptr); - zval_opt_copy_ctor(zptr); - - incdec_op(zptr); - } else { - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval rv; - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - zval z_copy; - - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } - ZVAL_DUP(retval, z); - ZVAL_DUP(&z_copy, z); - incdec_op(&z_copy); - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - zval_ptr_dtor(&z_copy); - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - ZVAL_NULL(retval); + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + binary_op(var_ptr, var_ptr, value TSRMLS_CC); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } } @@ -30003,246 +24049,371 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_post_incdec_property_helper_SPEC_UNUSED_VAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_post_incdec_property_helper_SPEC_UNUSED_VAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; - zval *offset; + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - /* here we are sure we are dealing with an object */ - do { - if (IS_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - zval_ptr_dtor_nogc(free_op2); +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *property; - zval *container; - - SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *property; - zval *container; - - SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; - zval *offset; + /* The generator object is stored in EX(return_value) */ + zend_generator *generator = (zend_generator *) EX(return_value); - SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } - if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - /* here we are sure we are dealing with an object */ - do { - if (IS_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ZVAL_COPY_VALUE(&generator->value, value); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + + /* Temporary variables don't need ctor copying */ + if (IS_UNUSED != IS_TMP_VAR) { + zval_opt_copy_ctor(&generator->value); } - } + } else { + zval *value_ptr = NULL; - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); - } + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + } else { + ZVAL_MAKE_REF(value_ptr); + } + ZVAL_COPY(&generator->value, value_ptr); - zval_ptr_dtor_nogc(free_op2); + } + } else { + zval *value = NULL; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST) { + ZVAL_DUP(&generator->value, value); + } else if (IS_UNUSED == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) { + ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_UNUSED == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1, free_op2; - zval *property; + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - container = _get_obj_zval_ptr_unused(execute_data); + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_DUP(&generator->key, key); + } else if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->key, key); + } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { + ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } else { + ZVAL_COPY_VALUE(&generator->key, key); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + } } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); } else { - return ZEND_FETCH_OBJ_R_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + generator->send_target = NULL; } + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container, *property; + return zend_binary_assign_op_helper_SPEC_UNUSED_TMP(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); +static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2, free_op_data1; + zval *object = _get_obj_zval_ptr_unused(execute_data); + zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zval *value; + zval *zptr; - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); -static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *object; - zval *property_name; + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); - SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(execute_data); - property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + /* here we are sure we are dealing with an object */ + if (opline->extended_value == ZEND_ASSIGN_OBJ + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { + zval *z = NULL; + zval rv; + + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv TSRMLS_CC); + } + } + if (z) { + if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + } + ZVAL_COPY_VALUE(z, value); + } +//??? if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + SEPARATE_ZVAL_IF_NOT_REF(z); + binary_op(z, z, value TSRMLS_CC); + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), z); + } + zval_ptr_dtor(z); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); @@ -30250,450 +24421,239 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *str = EX_VAR(opline->result.var); - zval *var; - zval var_copy; - int use_copy = 0; + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; + zval *value, *container; SAVE_OPLINE(); - var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_UNUSED == IS_UNUSED) { - /* Initialize for erealloc in add_string_to_string */ - ZVAL_EMPTY_STRING(str); + container = _get_obj_zval_ptr_unused(execute_data); + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (Z_TYPE_P(var) != IS_STRING) { - if (IS_VAR != IS_TMP_VAR) { - ZVAL_DEREF(var); + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_UNUSED == IS_VAR && !0) { + Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } - if (Z_TYPE_P(var) != IS_STRING) { - use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); - if (use_copy) { - var = &var_copy; - } - } + zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } - add_string_to_string(str, str, var); - if (use_copy) { - zend_string_release(Z_STR_P(var)); + if (UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } - /* original comment, possibly problematic: - * FREE_OP is missing intentionally here - we're always working on the same temporary variable - * (Zeev): I don't think it's problematic, we only use variables - * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're - * string offsets or overloaded objects - */ + + if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + binary_op(var_ptr, var_ptr, value TSRMLS_CC); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + } + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_free_op free_op2; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; + zval *var_ptr; + zval *value; SAVE_OPLINE(); + value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + var_ptr = NULL; - function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_VAR != IS_CONST && - UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } - object = _get_obj_zval_ptr_unused(execute_data); - - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); - } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - zval_ptr_dtor_nogc(free_op2); - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } + } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); - } - - obj = Z_OBJ_P(object); - called_scope = obj->ce; - - if (IS_VAR != IS_CONST || - EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { - zend_object *orig_obj = obj; - - if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); - } + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_VAR == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(obj == orig_obj)) { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } } - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; - } else { - GC_REFCOUNT(obj)++; /* For $this pointer */ - } - - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE - array = EX_VAR(opline->result.var); - if (IS_UNUSED != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - ZVAL_NEW_ARR(array); - zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); +} - if (IS_UNUSED != IS_UNUSED) { - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init(Z_ARRVAL_P(array), 0); - } - } +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (IS_UNUSED == IS_UNUSED) { - ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_UNUSED != IS_UNUSED - } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#endif + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *container; - zval *offset; - zend_ulong hval; - - SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - if (IS_UNUSED != IS_UNUSED) { - ZVAL_DEREF(container); - } - SEPARATE_ZVAL_NOREF(container); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); -offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); - } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2); - } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - zval_ptr_dtor_nogc(free_op2); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *container; - zval *offset; - SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); +} - if (IS_UNUSED != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->unset_property) { - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to unset property of non-object"); - } - } - zval_ptr_dtor_nogc(free_op2); +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *container; - int result; - zend_ulong hval; - zval *offset; - SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); - zval *value; - zend_string *str; +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } - } -str_index_prop: - value = zend_hash_find_ind(ht, str); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - value = NULL; - break; - } - } + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - if (opline->extended_value & ZEND_ISSET) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); - } - } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { - result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check element of non-array"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ - zval tmp; +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - result = 0; - if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(offset); - } - if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ - || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ - && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { - ZVAL_DUP(&tmp, offset); - convert_to_long(&tmp); - offset = &tmp; - } - } - if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { - if ((opline->extended_value & ZEND_ISSET) || - Z_STRVAL_P(container)[offset->value.lval] != '0') { - result = 1; - } - } - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *container; - int result; - zval *offset; - - SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_UNUSED_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -32076,15 +26036,10 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLE } if (Z_TYPE_P(var) != IS_STRING) { - if (IS_CV != IS_TMP_VAR) { - ZVAL_DEREF(var); - } - if (Z_TYPE_P(var) != IS_STRING) { - use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); + use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); - if (use_copy) { - var = &var_copy; - } + if (use_copy) { + var = &var_copy; } } add_string_to_string(str, str, var); @@ -32436,7 +26391,7 @@ num_index_prop: result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_CV == IS_CV || IS_CV == IS_VAR) { + if (IS_CV & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -32633,2482 +26588,2682 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_binary_assign_op_helper_SPEC_UNUSED_CV(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - - SAVE_OPLINE(); - bitwise_not_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC) TSRMLS_CC); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - - SAVE_OPLINE(); - boolean_not_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC) TSRMLS_CC); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *var_ptr; - - SAVE_OPLINE(); - var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - fast_increment_function(var_ptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - } - ZEND_VM_NEXT_OPCODE(); - } - - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - increment_function(var_ptr); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + return zend_binary_assign_op_helper_SPEC_UNUSED_CV(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *var_ptr; + zend_free_op free_op2; + zval *object; + zval *property; + zval *retval; + zval *zptr; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + object = _get_obj_zval_ptr_unused(execute_data); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - fast_decrement_function(var_ptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - } - ZEND_VM_NEXT_OPCODE(); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ } - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); + zval_ptr_dtor_nogc(free_op2); if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_NULL(retval); } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - decrement_function(var_ptr); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + /* here we are sure we are dealing with an object */ -static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - zval *var_ptr; + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - SAVE_OPLINE(); - var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { + zval rv; - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } + if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - fast_increment_function(var_ptr); - ZEND_VM_NEXT_OPCODE(); - } + if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + } + ZVAL_COPY_VALUE(z, value); + } + if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + SEPARATE_ZVAL_IF_NOT_REF(z); + incdec_op(z); + ZVAL_COPY_VALUE(retval, z); + Z_OBJ_HT_P(object)->write_property(object, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + SELECTIVE_PZVAL_LOCK(retval, opline); + zval_ptr_dtor(z); + } else { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(retval); + } + } } - ZVAL_DEREF(var_ptr); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - zval_opt_copy_ctor(var_ptr); - - increment_function(var_ptr); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE + return zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - zval *var_ptr; +static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *object; + zval *property; + zval *retval; + zval *zptr; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + object = _get_obj_zval_ptr_unused(execute_data); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - fast_decrement_function(var_ptr); - ZEND_VM_NEXT_OPCODE(); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ } - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); + zval_ptr_dtor_nogc(free_op2); + ZVAL_NULL(retval); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - ZVAL_DEREF(var_ptr); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - zval_opt_copy_ctor(var_ptr); + /* here we are sure we are dealing with an object */ - decrement_function(var_ptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + ZVAL_DEREF(zptr); + ZVAL_COPY_VALUE(retval, zptr); + zval_opt_copy_ctor(zptr); -static int ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + incdec_op(zptr); + } else { + if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { + zval rv; + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval z_copy; - zval *z; + if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - SAVE_OPLINE(); - z = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + } + ZVAL_COPY_VALUE(z, value); + } + ZVAL_DUP(retval, z); + ZVAL_DUP(&z_copy, z); + incdec_op(&z_copy); + if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + zval_ptr_dtor(&z_copy); + zval_ptr_dtor(z); + } else { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); + ZVAL_NULL(retval); + } + } - zend_print_variable(z TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_PRINT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE + return zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - ZVAL_LONG(EX_VAR(opline->result.var), 1); - return ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zval *container; + zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); - val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } - } + container = _get_obj_zval_ptr_unused(execute_data); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (i_zend_is_true(val TSRMLS_CC)) { - opline++; + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + ZVAL_NULL(EX_VAR(opline->result.var)); } else { - opline = opline->op2.jmp_addr; - } + zval *retval; - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + /* here we are sure we are dealing with an object */ + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); + + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } + } + + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } while (0); } - ZEND_VM_JMP(opline); + + zval_ptr_dtor_nogc(free_op2); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *val; + zend_free_op free_op1, free_op2; + zval *property; + zval *container; SAVE_OPLINE(); - val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_CV == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); - } + container = _get_obj_zval_ptr_unused(execute_data); + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (i_zend_is_true(val TSRMLS_CC)) { - opline = opline->op2.jmp_addr; - } else { - opline++; + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *val; + zend_free_op free_op1, free_op2; + zval *property; + zval *container; SAVE_OPLINE(); - val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + container = _get_obj_zval_ptr_unused(execute_data); - if (IS_CV == IS_TMP_VAR) { - if (EXPECTED(Z_TYPE_P(val) == IS_TRUE)) { - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - - if (i_zend_is_true(val TSRMLS_CC)) { - opline = (zend_op*)(((char*)opline) + opline->extended_value); - } else { - opline = opline->op2.jmp_addr; + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_JMP(opline); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zval *container; + zend_free_op free_op2; + zval *offset; SAVE_OPLINE(); - val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + container = _get_obj_zval_ptr_unused(execute_data); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_CV == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } - } + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; - if (i_zend_is_true(val TSRMLS_CC)) { + /* here we are sure we are dealing with an object */ + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); - ZVAL_TRUE(EX_VAR(opline->result.var)); - opline++; - } else { + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } + } - ZVAL_FALSE(EX_VAR(opline->result.var)); - opline = opline->op2.jmp_addr; - } - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } while (0); } - ZEND_VM_JMP(opline); + + zval_ptr_dtor_nogc(free_op2); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *container; - zval *val; + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + /* Behave like FETCH_OBJ_W */ + zend_free_op free_op1, free_op2; + zval *property; - SAVE_OPLINE(); - val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + SAVE_OPLINE(); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + container = _get_obj_zval_ptr_unused(execute_data); - if (IS_CV == IS_TMP_VAR) { - if (Z_TYPE_P(val) == IS_TRUE) { - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); - ZEND_VM_CONTINUE(); - } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline + 1); - ZEND_VM_CONTINUE(); + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - } - if (i_zend_is_true(val TSRMLS_CC)) { - ZVAL_TRUE(EX_VAR(opline->result.var)); - opline = opline->op2.jmp_addr; - } else { - ZVAL_FALSE(EX_VAR(opline->result.var)); - opline++; - } - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + return ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *retval_ptr; - + zend_free_op free_op1, free_op2; + zval *container, *property; SAVE_OPLINE(); - retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - if (!EX(return_value)) { - - } else { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { - zval_copy_ctor_func(EX(return_value)); - } - } - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(retval_ptr)) { - ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr)); + container = _get_obj_zval_ptr_unused(execute_data); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); - } - } + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *retval_ptr; - + zend_free_op free_op2; + zval *object; + zval *property_name; SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - do { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR || - (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { - /* Not supposed to happen, but we'll allow it */ - zend_error(E_NOTICE, "Only variable references should be returned by reference"); - - retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (!EX(return_value)) { - if (IS_CV == IS_TMP_VAR) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); - } - } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor_no_imm(EX(return_value)); - } - } - break; - } + /* assign_obj has two opcodes! */ + CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); +} - retval_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); +static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *str = EX_VAR(opline->result.var); + zval *var; + zval var_copy; + int use_copy = 0; - if (IS_CV == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); - } + SAVE_OPLINE(); + var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_CV == IS_VAR) { - if (retval_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { - zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); - } - break; - } - } + if (IS_UNUSED == IS_UNUSED) { + /* Initialize for erealloc in add_string_to_string */ + ZVAL_EMPTY_STRING(str); + } - if (EX(return_value)) { - ZVAL_MAKE_REF(retval_ptr); - Z_ADDREF_P(retval_ptr); - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + if (Z_TYPE_P(var) != IS_STRING) { + use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC); + + if (use_copy) { + var = &var_copy; } - } while (0); + } + add_string_to_string(str, str, var); - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (use_copy) { + zend_string_release(Z_STR_P(var)); + } + /* original comment, possibly problematic: + * FREE_OP is missing intentionally here - we're always working on the same temporary variable + * (Zeev): I don't think it's problematic, we only use variables + * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're + * string offsets or overloaded objects + */ + zval_ptr_dtor_nogc(free_op2); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - + zval *function_name; + zend_free_op free_op2; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; SAVE_OPLINE(); - value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Can only throw objects"); + zend_error_noreturn(E_ERROR, "Method name must be a string"); } - zend_exception_save(TSRMLS_C); - if (IS_CV != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } + object = _get_obj_zval_ptr_unused(execute_data); - zend_throw_exception_object(value TSRMLS_CC); - zend_exception_restore(TSRMLS_C); + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; - HANDLE_EXCEPTION(); -} + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); + } -static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zval_ptr_dtor_nogc(free_op2); + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } - varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - arg = ZEND_CALL_ARG(EX(call), opline->op2.num); - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(varptr)) { - ZVAL_COPY(arg, Z_REFVAL_P(varptr)); + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); - } else { - ZVAL_COPY_VALUE(arg, varptr); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; } + ZEND_VM_JMP(++opline); } - ZEND_VM_NEXT_OPCODE(); -} -static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + obj = Z_OBJ_P(object); + called_scope = obj->ce; - zval *varptr, *arg; + if ((IS_TMP_VAR|IS_VAR) != IS_CONST || + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { + zend_object *orig_obj = obj; - SAVE_OPLINE(); + if (UNEXPECTED(obj->handlers->get_method == NULL)) { + zend_error_noreturn(E_ERROR, "Object does not support method calls"); + } - if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) { - if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - return ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); } } - varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || - (Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) && - (Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) { - - ZVAL_MAKE_REF(varptr); - if (IS_CV == IS_CV) { - Z_ADDREF_P(varptr); - } + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + obj = NULL; } else { - if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? - !(opline->extended_value & ZEND_ARG_SEND_SILENT) : - !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - zend_error(E_STRICT, "Only variables should be passed by reference"); - } + GC_REFCOUNT(obj)++; /* For $this pointer */ } - arg = ZEND_CALL_ARG(EX(call), opline->op2.num); - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - ZVAL_COPY_VALUE(arg, varptr); + EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zval *array; + uint32_t size; USE_OPLINE - zval *varptr, *arg; - - SAVE_OPLINE(); - varptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + array = EX_VAR(opline->result.var); + if (IS_UNUSED != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + } else { + size = 0; + } + ZVAL_NEW_ARR(array); + zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); - if (IS_CV == IS_VAR && UNEXPECTED(varptr == NULL)) { - zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); + if (IS_UNUSED != IS_UNUSED) { + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init(Z_ARRVAL_P(array), 0); + } } - arg = ZEND_CALL_ARG(EX(call), opline->op2.num); - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - if (IS_CV == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) { - ZVAL_NEW_REF(arg, &EG(uninitialized_zval)); + if (IS_UNUSED == IS_UNUSED) { ZEND_VM_NEXT_OPCODE(); +#if 0 || IS_UNUSED != IS_UNUSED + } else { + return ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +#endif } +} - if (Z_ISREF_P(varptr)) { - Z_ADDREF_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); - } else if (IS_CV == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { - ZVAL_NEW_REF(arg, varptr); +static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *container; + zval *offset; + zend_ulong hval; + + SAVE_OPLINE(); + container = _get_obj_zval_ptr_unused(execute_data); + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + SEPARATE_ZVAL_NOREF(container); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); +offset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; + } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } + zval_ptr_dtor_nogc(free_op2); + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ } else { - ZVAL_NEW_REF(arg, varptr); - Z_ADDREF_P(arg); - ZVAL_REF(varptr, Z_REF_P(arg)); + zval_ptr_dtor_nogc(free_op2); } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; - + zend_free_op free_op2; + zval *container; + zval *offset; - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + SAVE_OPLINE(); + container = _get_obj_zval_ptr_unused(execute_data); + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } - varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - arg = ZEND_CALL_ARG(EX(call), opline->op2.num); - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(varptr)) { - ZVAL_COPY(arg, Z_REFVAL_P(varptr)); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - } else { - ZVAL_COPY_VALUE(arg, varptr); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg); + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->unset_property) { + Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to unset property of non-object"); } } + zval_ptr_dtor_nogc(free_op2); + + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *arg, *param, tmp; - - - arg = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - param = ZEND_CALL_ARG(EX(call), opline->op2.num); - - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - // TODO: Scalar values don't have reference counters anymore. - // They are assumed to be 1, and they may be easily passed by - // reference now. However, previously scalars with refcount==1 - // might be passed and with refcount>1 might not. We can support - // only single behavior ??? -#if 0 - if (Z_REFCOUNTED_P(arg) && - // This solution breaks the following test (omit warning message) ??? - // Zend/tests/bug61273.phpt - // ext/reflection/tests/bug42976.phpt - // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt -#else - if (!Z_REFCOUNTED_P(arg) || - // This solution breaks the following test (emit warning message) ??? - // ext/pdo_sqlite/tests/pdo_005.phpt -#endif - (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) { + zend_free_op free_op2; + zval *container; + int result; + zend_ulong hval; + zval *offset; - if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { + SAVE_OPLINE(); + container = _get_obj_zval_ptr_unused(execute_data); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", - opline->op2.num, - EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "", - EX(call)->func->common.scope ? "::" : "", - EX(call)->func->common.function_name->val); + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value; + zend_string *str; - if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { - OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); - } - if (Z_OBJ(EX(call)->This)) { - OBJ_RELEASE(Z_OBJ(EX(call)->This)); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } - EX(call)->func = (zend_function*)&zend_pass_function; - EX(call)->called_scope = NULL; - Z_OBJ(EX(call)->This) = NULL; - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } +str_index_prop: + value = zend_hash_find_ind(ht, str); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else { + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 1; + goto num_index_prop; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto isset_again; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + value = NULL; + break; + } + } - if (Z_REFCOUNTED_P(arg)) { - Z_DELREF_P(arg); + if (opline->extended_value & ZEND_ISSET) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check element of non-array"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ + zval tmp; + + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) { + ZVAL_DEREF(offset); + } + if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ + || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ + && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { + ZVAL_DUP(&tmp, offset); + convert_to_long(&tmp); + offset = &tmp; } - ZVAL_DUP(&tmp, arg); - ZVAL_NEW_REF(arg, &tmp); - Z_ADDREF_P(arg); - } else if (!Z_ISREF_P(arg)) { - ZVAL_NEW_REF(arg, arg); - Z_ADDREF_P(arg); - } else if (Z_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); } - ZVAL_COPY_VALUE(param, arg); - } else if (Z_ISREF_P(arg) && - /* don't separate references for __call */ - (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { - ZVAL_DUP(param, Z_REFVAL_P(arg)); + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { + if ((opline->extended_value & ZEND_ISSET) || + Z_STRVAL_P(container)[offset->value.lval] != '0') { + result = 1; + } + } + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } } else { - ZVAL_COPY(param, arg); + result = ((opline->extended_value & ZEND_ISSET) == 0); } - ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *retval = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ - ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC) TSRMLS_CC)); + zval_ptr_dtor_nogc(free_op2); + ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *obj; - zend_class_entry *ce; - zend_function *clone; - zend_object_clone_obj_t clone_call; + zend_free_op free_op2; + zval *container; + int result; + zval *offset; SAVE_OPLINE(); - obj = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_CONST || - (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "__clone method called on non-object"); - } + container = _get_obj_zval_ptr_unused(execute_data); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - ce = Z_OBJCE_P(obj); - clone = ce ? ce->clone : NULL; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; - if (UNEXPECTED(clone_call == NULL)) { - if (ce) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); + if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; } - } - - if (ce && clone) { - if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); - } - } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); - } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); } - if (EXPECTED(EG(exception) == NULL)) { - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj TSRMLS_CC)); - if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var))); - } - } + zval_ptr_dtor_nogc(free_op2); + ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; - zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + bitwise_not_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC) TSRMLS_CC); - switch (opline->extended_value) { - case IS_NULL: - /* This code is taken from convert_to_null. However, it does not seems very useful, - * because a conversion to null always results in the same value. This could only - * be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */ -#if 0 - if (IS_CV == IS_VAR || IS_CV == IS_CV) { - ZVAL_DEREF(expr); - } - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) { - if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL TSRMLS_CC) == SUCCESS) { - break; - } - } -#endif + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - ZVAL_NULL(result); - break; - case _IS_BOOL: - ZVAL_BOOL(result, zend_is_true(expr TSRMLS_CC)); - break; - case IS_LONG: - ZVAL_LONG(result, zval_get_long(expr)); - break; - case IS_DOUBLE: - ZVAL_DOUBLE(result, zval_get_double(expr)); - break; - case IS_STRING: - ZVAL_STR(result, zval_get_string(expr)); - break; - default: - /* If value is already of correct type, return it directly */ - if (Z_TYPE_P(expr) == opline->extended_value) { - ZVAL_COPY_VALUE(result, expr); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) { - zval_copy_ctor_func(result); - } - } else if (IS_CV != IS_TMP_VAR) { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } +static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - if (opline->extended_value == IS_ARRAY) { - if (Z_TYPE_P(expr) != IS_OBJECT) { - ZVAL_NEW_ARR(result); - zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0); - if (Z_TYPE_P(expr) != IS_NULL) { - expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { - zval_copy_ctor_func(expr); - } - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } - } else { - ZVAL_COPY_VALUE(result, expr); - Z_ADDREF_P(result); - convert_to_array(result); - } - } else { - if (Z_TYPE_P(expr) != IS_ARRAY) { - object_init(result); - if (Z_TYPE_P(expr) != IS_NULL) { - expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { - zval_copy_ctor_func(expr); - } - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } - } else { - ZVAL_COPY_VALUE(result, expr); - zval_opt_copy_ctor(result); - convert_to_object(result); - } - } - } + SAVE_OPLINE(); + boolean_not_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_op_array *new_op_array=NULL; - zval *inc_filename; - zval tmp_inc_filename; - zend_bool failure_retval=0; + zval *var_ptr; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - ZVAL_UNDEF(&tmp_inc_filename); - if (Z_TYPE_P(inc_filename) != IS_STRING) { - ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); - inc_filename = &tmp_inc_filename; + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) { - if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) { - zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); - } else { - zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_increment_function(var_ptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); } - } else { - switch (opline->extended_value) { - case ZEND_INCLUDE_ONCE: - case ZEND_REQUIRE_ONCE: { - zend_file_handle file_handle; - char *resolved_path; - - resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename) TSRMLS_CC); - if (resolved_path) { - failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path)); - } else { - resolved_path = Z_STRVAL_P(inc_filename); - } + ZEND_VM_NEXT_OPCODE(); + } - if (failure_retval) { - /* do nothing, file already included */ - } else if (SUCCESS == zend_stream_open(resolved_path, &file_handle TSRMLS_CC)) { + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } - if (!file_handle.opened_path) { - file_handle.opened_path = estrdup(resolved_path); - } + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); - if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) { - new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC); - zend_destroy_file_handle(&file_handle TSRMLS_CC); - } else { - zend_file_handle_dtor(&file_handle TSRMLS_CC); - failure_retval=1; - } - } else { - if (opline->extended_value == ZEND_INCLUDE_ONCE) { - zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); - } else { - zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); - } - } - if (resolved_path != Z_STRVAL_P(inc_filename)) { - efree(resolved_path); - } - } - break; - case ZEND_INCLUDE: - case ZEND_REQUIRE: - new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC); - break; - case ZEND_EVAL: { - char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); + increment_function(var_ptr); - new_op_array = zend_compile_string(inc_filename, eval_desc TSRMLS_CC); - efree(eval_desc); - } - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) { - zend_string_release(Z_STR(tmp_inc_filename)); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } else if (EXPECTED(new_op_array != NULL)) { - zval *return_value = NULL; - zend_execute_data *call; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (RETURN_VALUE_USED(opline)) { - return_value = EX_VAR(opline->result.var); - } +static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - new_op_array->scope = EG(scope); /* ??? */ + zval *var_ptr; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, - (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL TSRMLS_CC); + SAVE_OPLINE(); + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (EX(symbol_table)) { - call->symbol_table = EX(symbol_table); - } else { - call->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); - } + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } - call->prev_execute_data = execute_data; - i_init_code_execute_data(call, new_op_array, return_value TSRMLS_CC); - if (EXPECTED(zend_execute_ex == execute_ex)) { - ZEND_VM_ENTER(); - } else { - ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); - zend_execute_ex(call TSRMLS_CC); + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_decrement_function(var_ptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); } + ZEND_VM_NEXT_OPCODE(); + } - destroy_op_array(new_op_array TSRMLS_CC); - efree_size(new_op_array, sizeof(zend_op_array)); - if (UNEXPECTED(EG(exception) != NULL)) { - zend_throw_exception_internal(NULL TSRMLS_CC); - HANDLE_EXCEPTION(); + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_BOOL(EX_VAR(opline->result.var), failure_retval); + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + decrement_function(var_ptr); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref, iterator, tmp; - HashTable *fe_ht; - zend_object_iterator *iter = NULL; - zend_class_entry *ce = NULL; - zend_bool is_empty = 0; + zval *var_ptr; SAVE_OPLINE(); + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if ((IS_CV == IS_CV || IS_CV == IS_VAR) && - (opline->extended_value & ZEND_FE_FETCH_BYREF)) { - array_ptr = array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - ZVAL_DEREF(array_ptr); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); - if (!Z_ISREF_P(array_ref)) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); - } - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce->get_iterator == NULL) { - Z_ADDREF_P(array_ptr); - } - array_ref = array_ptr; - } else { - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } - } else { - array_ptr = array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - ZVAL_DEREF(array_ptr); - if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&tmp, array_ptr); - if (Z_OPT_IMMUTABLE_P(&tmp)) { - zval_copy_ctor_func(&tmp); - } - array_ref = array_ptr = &tmp; - if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce && ce->get_iterator) { - Z_DELREF_P(array_ref); - } - } - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (!ce->get_iterator) { - if (IS_CV == IS_CV) { - Z_ADDREF_P(array_ref); - } - } - } else if (Z_IMMUTABLE_P(array_ref)) { - if (IS_CV == IS_CV) { - zval_copy_ctor_func(array_ref); - Z_ADDREF_P(array_ref); - } else { - ZVAL_COPY_VALUE(&tmp, array_ref); - zval_copy_ctor_func(&tmp); - array_ptr = array_ref = &tmp; - } - } else if (Z_REFCOUNTED_P(array_ref)) { - if (IS_CV == IS_CONST || - (IS_CV == IS_CV && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 1) || - (IS_CV == IS_VAR && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 2)) { - if (IS_CV == IS_VAR) { - Z_DELREF_P(array_ref); - } - ZVAL_DUP(&tmp, array_ref); - array_ptr = array_ref = &tmp; - } else if (IS_CV == IS_CV || IS_CV == IS_VAR) { - if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) { - ZVAL_UNREF(array_ref); - array_ptr = array_ref; - } - if (Z_IMMUTABLE_P(array_ptr)) { - zval_copy_ctor_func(array_ptr); - } else if (Z_ISREF_P(array_ref) && - Z_COPYABLE_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1) { - Z_DELREF_P(array_ptr); - zval_copy_ctor_func(array_ptr); - } - if (IS_CV == IS_CV) { - Z_ADDREF_P(array_ref); - } - } - } + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (ce && ce->get_iterator) { - iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF TSRMLS_CC); - - if (IS_CV == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) { - - } - if (iter && EXPECTED(EG(exception) == NULL)) { - ZVAL_OBJ(&iterator, &iter->std); - array_ptr = array_ref = &iterator; - } else { - if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + fast_increment_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); + } - } - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name->val); - } - zend_throw_exception_internal(NULL TSRMLS_CC); - HANDLE_EXCEPTION(); - } + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + ZVAL_DEREF(var_ptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_opt_copy_ctor(var_ptr); - if (iter) { - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + increment_function(var_ptr); - } - HANDLE_EXCEPTION(); - } - } - is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS; - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - } - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ - } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var); - HashPosition pos = 0; - Bucket *p; +static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - while (1) { - if (pos >= fe_ht->nNumUsed) { - is_empty = 1; - if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + zval *var_ptr; - } - ZEND_VM_JMP(opline->op2.jmp_addr); - } - p = fe_ht->arData + pos; - if (Z_TYPE(p->val) == IS_UNDEF || - (Z_TYPE(p->val) == IS_INDIRECT && - Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) { - pos++; - continue; - } - if (!ce || - !p->key || - zend_check_property_access(Z_OBJ_P(array_ptr), p->key TSRMLS_CC) == SUCCESS) { - break; - } - pos++; - } - fe_ht->nInternalPointer = pos; - ptr->pos = pos; - ptr->ht = fe_ht; - ptr->h = fe_ht->arData[pos].h; - ptr->key = fe_ht->arData[pos].key; - is_empty = 0; - } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - is_empty = 1; - } + SAVE_OPLINE(); + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + fast_decrement_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); } - if (is_empty) { - ZEND_VM_JMP(opline->op2.jmp_addr); - } else { + + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + ZVAL_NULL(EX_VAR(opline->result.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } + + ZVAL_DEREF(var_ptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_opt_copy_ctor(var_ptr); + + decrement_function(var_ptr); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 || (IS_CV != IS_UNUSED) USE_OPLINE + zval *z; + SAVE_OPLINE(); - if (IS_CV != IS_UNUSED) { + z = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zval *ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_print_variable(z TSRMLS_CC); - if (Z_TYPE_P(ptr) == IS_LONG) { - EG(exit_status) = Z_LVAL_P(ptr); - } else { - zend_print_variable(ptr TSRMLS_CC); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_PRINT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + ZVAL_LONG(EX_VAR(opline->result.var), 1); + return ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *val; + + SAVE_OPLINE(); + val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); } + } + if (i_zend_is_true(val TSRMLS_CC)) { + opline++; + } else { + opline = opline->op2.jmp_addr; } -#endif - zend_bailout(); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ + + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - int is_ref = 0; + zval *val; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { - is_ref = 1; - value = Z_REFVAL_P(value); + if (IS_CV == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } } - if (i_zend_is_true(value TSRMLS_CC)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { - zval_copy_ctor_func(EX_VAR(opline->result.var)); - } - } else if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } else if (IS_CV == IS_VAR && is_ref) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - ZEND_VM_JMP(opline->op2.jmp_addr); + if (i_zend_is_true(val TSRMLS_CC)) { + opline = opline->op2.jmp_addr; + } else { + opline++; } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - int is_ref = 0; + zval *val; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { - is_ref = 1; - value = Z_REFVAL_P(value); + if (IS_CV == IS_TMP_VAR) { + if (EXPECTED(Z_TYPE_P(val) == IS_TRUE)) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } } - if (Z_TYPE_P(value) > IS_NULL) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { - zval_copy_ctor_func(EX_VAR(opline->result.var)); - } - } else if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } else if (IS_CV == IS_VAR && is_ref) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - - } - ZEND_VM_JMP(opline->op2.jmp_addr); + if (i_zend_is_true(val TSRMLS_CC)) { + opline = (zend_op*)(((char*)opline) + opline->extended_value); + } else { + opline = opline->op2.jmp_addr; } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; + zval *val; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { - ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value)); + if (IS_CV == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } + } + + if (i_zend_is_true(val TSRMLS_CC)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline++; } else { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { - zval_copy_ctor_func(EX_VAR(opline->result.var)); - } - } else if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } + + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline = opline->op2.jmp_addr; } - ZEND_VM_NEXT_OPCODE(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; + zval *val; SAVE_OPLINE(); - value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - } else { - if (Z_TYPE_P(value) < IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 0); - } else if (Z_TYPE_P(value) == IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 1); - } else if (Z_TYPE_P(value) <= IS_DOUBLE) { - zend_string *str = zval_get_string(value); - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); - } else if (Z_TYPE_P(value) == IS_OBJECT) { - zend_string *str; - zval tmp; + val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - ZVAL_COPY(&tmp, value); - if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) { - goto strlen_error; - } - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zval_dtor(&tmp); - } else { -strlen_error: - zend_error(E_WARNING, "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)); + if (IS_CV == IS_TMP_VAR) { + if (Z_TYPE_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); } } + if (i_zend_is_true(val TSRMLS_CC)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline = opline->op2.jmp_addr; + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline++; + } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(opline); } -static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; + zval *retval_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - switch (opline->extended_value) { - case IS_NULL: - case IS_LONG: - case IS_DOUBLE: - case IS_STRING: - case IS_ARRAY: - ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == opline->extended_value); - break; - case _IS_BOOL: - ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE); - break; - case IS_OBJECT: - if (Z_TYPE_P(value) == opline->extended_value) { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); + retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + if (!EX(return_value)) { + + } else { + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { + zval_copy_ctor_func(EX(return_value)); } - } else { - ZVAL_FALSE(EX_VAR(opline->result.var)); } - break; - case IS_RESOURCE: - if (Z_TYPE_P(value) == opline->extended_value) { - const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value) TSRMLS_CC); - ZVAL_BOOL(EX_VAR(opline->result.var), type_name != NULL); - } else { - ZVAL_FALSE(EX_VAR(opline->result.var)); + } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(retval_ptr)) { + ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr)); + + } else { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } - break; - EMPTY_SWITCH_DEFAULT_CASE() + } } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *retval_ptr; SAVE_OPLINE(); - fast_add_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + do { + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR || + (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { + /* Not supposed to happen, but we'll allow it */ + zend_error(E_NOTICE, "Only variable references should be returned by reference"); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + if (!EX(return_value)) { + if (IS_CV == IS_TMP_VAR) { -static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + } + } else { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + if (IS_CV != IS_TMP_VAR) { + zval_opt_copy_ctor_no_imm(EX(return_value)); + } + } + break; + } + retval_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - SAVE_OPLINE(); - fast_sub_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); + } + + if (IS_CV == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (EX(return_value)) { + ZVAL_NEW_REF(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + } + break; + } + } + if (EX(return_value)) { + ZVAL_MAKE_REF(retval_ptr); + Z_ADDREF_P(retval_ptr); + ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; + } + } while (0); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *value; SAVE_OPLINE(); - fast_mul_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Can only throw objects"); + } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + zend_exception_save(TSRMLS_C); + if (IS_CV != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + + zend_throw_exception_object(value TSRMLS_CC); + zend_exception_restore(TSRMLS_C); + + HANDLE_EXCEPTION(); } -static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *varptr, *arg; - SAVE_OPLINE(); - fast_div_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); - + varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + arg = ZEND_CALL_ARG(EX(call), opline->op2.num); + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + if (Z_ISREF_P(varptr)) { + ZVAL_COPY(arg, Z_REFVAL_P(varptr)); - CHECK_EXCEPTION(); + } else { + ZVAL_COPY_VALUE(arg, varptr); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg); + } + } ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *varptr, *arg; SAVE_OPLINE(); - fast_mod_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} -static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) { + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { + return ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + } + varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || + (Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) && + (Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) { - SAVE_OPLINE(); - shift_left_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + ZVAL_MAKE_REF(varptr); + if (IS_CV == IS_CV) { + Z_ADDREF_P(varptr); + } + } else { + if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? + !(opline->extended_value & ZEND_ARG_SEND_SILENT) : + !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { + zend_error(E_STRICT, "Only variables should be passed by reference"); + } + } + arg = ZEND_CALL_ARG(EX(call), opline->op2.num); + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + ZVAL_COPY_VALUE(arg, varptr); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *varptr, *arg; SAVE_OPLINE(); - shift_right_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + varptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(varptr == NULL)) { + zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); + } + arg = ZEND_CALL_ARG(EX(call), opline->op2.num); + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + if (IS_CV == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) { + ZVAL_NEW_REF(arg, &EG(uninitialized_zval)); + ZEND_VM_NEXT_OPCODE(); + } + + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + } else if (IS_CV == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { + ZVAL_NEW_REF(arg, varptr); + } else { + ZVAL_NEW_REF(arg, varptr); + Z_ADDREF_P(arg); + ZVAL_REF(varptr, Z_REF_P(arg)); + } - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *varptr, *arg; - SAVE_OPLINE(); - concat_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); - + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { + return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + arg = ZEND_CALL_ARG(EX(call), opline->op2.num); + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; + if (Z_ISREF_P(varptr)) { + ZVAL_COPY(arg, Z_REFVAL_P(varptr)); - CHECK_EXCEPTION(); + } else { + ZVAL_COPY_VALUE(arg, varptr); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg); + } + } ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *arg, *param, tmp; - SAVE_OPLINE(); - fast_is_identical_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + arg = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + param = ZEND_CALL_ARG(EX(call), opline->op2.num); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { + // TODO: Scalar values don't have reference counters anymore. + // They are assumed to be 1, and they may be easily passed by + // reference now. However, previously scalars with refcount==1 + // might be passed and with refcount>1 might not. We can support + // only single behavior ??? +#if 0 + if (Z_REFCOUNTED_P(arg) && + // This solution breaks the following test (omit warning message) ??? + // Zend/tests/bug61273.phpt + // ext/reflection/tests/bug42976.phpt + // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt +#else + if (!Z_REFCOUNTED_P(arg) || + // This solution breaks the following test (emit warning message) ??? + // ext/pdo_sqlite/tests/pdo_005.phpt +#endif + (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { -static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", + opline->op2.num, + EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "", + EX(call)->func->common.scope ? "::" : "", + EX(call)->func->common.function_name->val); - zval *result = EX_VAR(opline->result.var); + if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { + OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); + } + if (Z_OBJ(EX(call)->This)) { + OBJ_RELEASE(Z_OBJ(EX(call)->This)); + } + EX(call)->func = (zend_function*)&zend_pass_function; + EX(call)->called_scope = NULL; + Z_OBJ(EX(call)->This) = NULL; - SAVE_OPLINE(); - fast_is_not_identical_function(result, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + if (Z_REFCOUNTED_P(arg)) { + Z_DELREF_P(arg); + } + ZVAL_DUP(&tmp, arg); + ZVAL_NEW_REF(arg, &tmp); + Z_ADDREF_P(arg); + } else if (!Z_ISREF_P(arg)) { + ZVAL_NEW_REF(arg, arg); + Z_ADDREF_P(arg); + } else if (Z_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + ZVAL_COPY_VALUE(param, arg); + } else if (Z_ISREF_P(arg) && + /* don't separate references for __call */ + (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { + ZVAL_DUP(param, Z_REFVAL_P(arg)); + } else { + ZVAL_COPY(param, arg); + } + ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *result = EX_VAR(opline->result.var); + zval *retval = EX_VAR(opline->result.var); SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); - + /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ + ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *result = EX_VAR(opline->result.var); + zval *obj; + zend_class_entry *ce; + zend_function *clone; + zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + obj = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); -static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "__clone method called on non-object"); + } - zval *result = EX_VAR(opline->result.var); + ce = Z_OBJCE_P(obj); + clone = ce ? ce->clone : NULL; + clone_call = Z_OBJ_HT_P(obj)->clone_obj; + if (UNEXPECTED(clone_call == NULL)) { + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); + } else { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + } + } - SAVE_OPLINE(); - fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + if (ce && clone) { + if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { + /* Ensure that if we're calling a private function, we're allowed to do so. + */ + if (UNEXPECTED(ce != EG(scope))) { + zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + } + } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { + /* Ensure that if we're calling a protected function, we're allowed to do so. + */ + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { + zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + } + } + } + if (EXPECTED(EG(exception) == NULL)) { + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj TSRMLS_CC)); + if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var))); + } + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *expr; zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); -static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + switch (opline->extended_value) { + case IS_NULL: + /* This code is taken from convert_to_null. However, it does not seems very useful, + * because a conversion to null always results in the same value. This could only + * be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */ +#if 0 + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + ZVAL_DEREF(expr); + } + if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) { + if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL TSRMLS_CC) == SUCCESS) { + break; + } + } +#endif + ZVAL_NULL(result); + break; + case _IS_BOOL: + ZVAL_BOOL(result, zend_is_true(expr TSRMLS_CC)); + break; + case IS_LONG: + ZVAL_LONG(result, zval_get_long(expr)); + break; + case IS_DOUBLE: + ZVAL_DOUBLE(result, zval_get_double(expr)); + break; + case IS_STRING: + ZVAL_STR(result, zval_get_string(expr)); + break; + default: + /* If value is already of correct type, return it directly */ + if (Z_TYPE_P(expr) == opline->extended_value) { + ZVAL_COPY_VALUE(result, expr); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) { + zval_copy_ctor_func(result); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } - SAVE_OPLINE(); - bitwise_or_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + if (opline->extended_value == IS_ARRAY) { + if (Z_TYPE_P(expr) != IS_OBJECT) { + ZVAL_NEW_ARR(result); + zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0); + if (Z_TYPE_P(expr) != IS_NULL) { + expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { + zval_copy_ctor_func(expr); + } + } else { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + } + } else { + ZVAL_COPY_VALUE(result, expr); + Z_ADDREF_P(result); + convert_to_array(result); + } + } else { + if (Z_TYPE_P(expr) != IS_ARRAY) { + object_init(result); + if (Z_TYPE_P(expr) != IS_NULL) { + expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { + zval_copy_ctor_func(expr); + } + } else { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + } + } else { + ZVAL_COPY_VALUE(result, expr); + zval_opt_copy_ctor(result); + convert_to_object(result); + } + } + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_op_array *new_op_array=NULL; + zval *inc_filename; + zval tmp_inc_filename; + zend_bool failure_retval=0; SAVE_OPLINE(); - bitwise_and_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + inc_filename = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ZVAL_UNDEF(&tmp_inc_filename); + if (Z_TYPE_P(inc_filename) != IS_STRING) { + ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); + inc_filename = &tmp_inc_filename; + } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) { + if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) { + zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + } else { + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + } + } else { + switch (opline->extended_value) { + case ZEND_INCLUDE_ONCE: + case ZEND_REQUIRE_ONCE: { + zend_file_handle file_handle; + char *resolved_path; -static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename) TSRMLS_CC); + if (resolved_path) { + failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path)); + } else { + resolved_path = Z_STRVAL_P(inc_filename); + } + + if (failure_retval) { + /* do nothing, file already included */ + } else if (SUCCESS == zend_stream_open(resolved_path, &file_handle TSRMLS_CC)) { + if (!file_handle.opened_path) { + file_handle.opened_path = estrdup(resolved_path); + } - SAVE_OPLINE(); - bitwise_xor_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) { + new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC); + zend_destroy_file_handle(&file_handle TSRMLS_CC); + } else { + zend_file_handle_dtor(&file_handle TSRMLS_CC); + failure_retval=1; + } + } else { + if (opline->extended_value == ZEND_INCLUDE_ONCE) { + zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + } else { + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + } + } + if (resolved_path != Z_STRVAL_P(inc_filename)) { + efree(resolved_path); + } + } + break; + case ZEND_INCLUDE: + case ZEND_REQUIRE: + new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC); + break; + case ZEND_EVAL: { + char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); + new_op_array = zend_compile_string(inc_filename, eval_desc TSRMLS_CC); + efree(eval_desc); + } + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } + if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) { + zend_string_release(Z_STR(tmp_inc_filename)); + } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } else if (EXPECTED(new_op_array != NULL)) { + zval *return_value = NULL; + zend_execute_data *call; -static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (RETURN_VALUE_USED(opline)) { + return_value = EX_VAR(opline->result.var); + } + new_op_array->scope = EG(scope); /* ??? */ - SAVE_OPLINE(); - boolean_xor_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, + (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL TSRMLS_CC); + if (EX(symbol_table)) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); + } - CHECK_EXCEPTION(); + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value TSRMLS_CC); + if (EXPECTED(zend_execute_ex == execute_ex)) { + ZEND_VM_ENTER(); + } else { + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call TSRMLS_CC); + } + + destroy_op_array(new_op_array TSRMLS_CC); + efree_size(new_op_array, sizeof(zend_op_array)); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + HANDLE_EXCEPTION(); + } + + } else if (RETURN_VALUE_USED(opline)) { + ZVAL_BOOL(EX_VAR(opline->result.var), failure_retval); + } ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data1; - zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - zval *property = opline->op2.zv; - zval *value; - zval *zptr; - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } + zval *array_ptr, *array_ref, iterator, tmp; + HashTable *fe_ht; + zend_object_iterator *iter = NULL; + zend_class_entry *ce = NULL; + zend_bool is_empty = 0; - if (IS_CV != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); + SAVE_OPLINE(); + + if ((IS_CV == IS_CV || IS_CV == IS_VAR) && + (opline->extended_value & ZEND_FE_FETCH_BYREF)) { + array_ptr = array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ZVAL_DEREF(array_ptr); + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + SEPARATE_ARRAY(array_ptr); + if (!Z_ISREF_P(array_ref)) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); + } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { + ce = Z_OBJCE_P(array_ptr); + if (ce->get_iterator == NULL) { + Z_ADDREF_P(array_ptr); + } + array_ref = array_ptr; + } else { + if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); + } + } else { + array_ptr = array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ZVAL_DEREF(array_ptr); + if (IS_CV == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&tmp, array_ptr); + if (Z_OPT_IMMUTABLE_P(&tmp)) { + zval_copy_ctor_func(&tmp); + } + array_ref = array_ptr = &tmp; + if (Z_TYPE_P(array_ptr) == IS_OBJECT) { + ce = Z_OBJCE_P(array_ptr); + if (ce && ce->get_iterator) { + Z_DELREF_P(array_ref); + } + } + } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { + ce = Z_OBJCE_P(array_ptr); + if (!ce->get_iterator) { + if (IS_CV == IS_CV) { + Z_ADDREF_P(array_ref); + } + } + } else if (Z_IMMUTABLE_P(array_ref)) { + if (IS_CV == IS_CV) { + zval_copy_ctor_func(array_ref); + Z_ADDREF_P(array_ref); + } else { + ZVAL_COPY_VALUE(&tmp, array_ref); + zval_copy_ctor_func(&tmp); + array_ptr = array_ref = &tmp; + } + } else if (Z_REFCOUNTED_P(array_ref)) { + if (IS_CV == IS_CONST || + (IS_CV == IS_CV && + !Z_ISREF_P(array_ref) && + Z_REFCOUNT_P(array_ref) > 1) || + (IS_CV == IS_VAR && + !Z_ISREF_P(array_ref) && + Z_REFCOUNT_P(array_ref) > 2)) { + if (IS_CV == IS_VAR) { + Z_DELREF_P(array_ref); + } + ZVAL_DUP(&tmp, array_ref); + array_ptr = array_ref = &tmp; + } else if (IS_CV == IS_CV || IS_CV == IS_VAR) { + if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) { + ZVAL_UNREF(array_ref); + array_ptr = array_ref; + } + if (Z_IMMUTABLE_P(array_ptr)) { + zval_copy_ctor_func(array_ptr); + } else if (Z_ISREF_P(array_ref) && + Z_COPYABLE_P(array_ptr) && + Z_REFCOUNT_P(array_ptr) > 1) { + Z_DELREF_P(array_ptr); + zval_copy_ctor_func(array_ptr); + } + if (IS_CV == IS_CV) { + Z_ADDREF_P(array_ref); + } + } + } } - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + if (ce && ce->get_iterator) { + iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF TSRMLS_CC); - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (IS_CV == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) { - FREE_OP(free_op_data1); + } + if (iter && EXPECTED(EG(exception) == NULL)) { + ZVAL_OBJ(&iterator, &iter->std); + array_ptr = array_ref = &iterator; + } else { + if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); + } + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name->val); + } + zend_throw_exception_internal(NULL TSRMLS_CC); + HANDLE_EXCEPTION(); } - } else { - /* here we are sure we are dealing with an object */ - if (opline->extended_value == ZEND_ASSIGN_OBJ - && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + } - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } else { - zval *z = NULL; - zval rv; + if (iter) { + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array_ref); + if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - } - } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv TSRMLS_CC); } + HANDLE_EXCEPTION(); } - if (z) { - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + } + is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS; + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array_ref); + if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + + } + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ + } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { + HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var); + HashPosition pos = 0; + Bucket *p; + + while (1) { + if (pos >= fe_ht->nNumUsed) { + is_empty = 1; + if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } -//??? if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - binary_op(z, z, value TSRMLS_CC); - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), z); - } - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); } + ZEND_VM_JMP(opline->op2.jmp_addr); + } + p = fe_ht->arData + pos; + if (Z_TYPE(p->val) == IS_UNDEF || + (Z_TYPE(p->val) == IS_INDIRECT && + Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) { + pos++; + continue; + } + if (!ce || + !p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key TSRMLS_CC) == SUCCESS) { + break; } + pos++; } - - FREE_OP(free_op_data1); + fe_ht->nInternalPointer = pos; + ptr->pos = pos; + ptr->ht = fe_ht; + ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; + is_empty = 0; + } else { + zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + is_empty = 1; } - /* assign_obj has two opcodes! */ - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); + if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + + } + if (is_empty) { + ZEND_VM_JMP(opline->op2.jmp_addr); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 || (IS_CV != IS_UNUSED) USE_OPLINE - zend_free_op free_op_data1; - zval *var_ptr, rv; - zval *value, *container; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } if (IS_CV != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_CV == IS_VAR && !0) { - Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ - } - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zval *dim = opline->op2.zv; - - zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - } - if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } + zval *ptr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + if (Z_TYPE_P(ptr) == IS_LONG) { + EG(exit_status) = Z_LVAL_P(ptr); + } else { + zend_print_variable(ptr TSRMLS_CC); } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - binary_op(var_ptr, var_ptr, value TSRMLS_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } } - - FREE_OP(free_op_data1); - - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); +#endif + zend_bailout(); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; zval *value; + int is_ref = 0; SAVE_OPLINE(); - value = opline->op2.zv; - var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { + is_ref = 1; + value = Z_REFVAL_P(value); } + if (i_zend_is_true(value TSRMLS_CC)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); + } + } else if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } else if (IS_CV == IS_VAR && is_ref) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - binary_op(var_ptr, var_ptr, value TSRMLS_CC); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + ZEND_VM_JMP(opline->op2.jmp_addr); } - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + zval *value; + int is_ref = 0; -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { + is_ref = 1; + value = Z_REFVAL_P(value); } -} -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (Z_TYPE_P(value) > IS_NULL) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); + } + } else if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } else if (IS_CV == IS_VAR && is_ref) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + ZEND_VM_JMP(opline->op2.jmp_addr); } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + zval *value; -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { + ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value)); + + } else { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); + } + } else if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } } + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *value; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + } else { + if (Z_TYPE_P(value) < IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 0); + } else if (Z_TYPE_P(value) == IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 1); + } else if (Z_TYPE_P(value) <= IS_DOUBLE) { + zend_string *str = zval_get_string(value); + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zend_string_release(str); + } else if (Z_TYPE_P(value) == IS_OBJECT) { + zend_string *str; + zval tmp; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) { + goto strlen_error; + } + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zval_dtor(&tmp); + } else { +strlen_error: + zend_error(E_WARNING, "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)); + } } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *value; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + switch (opline->extended_value) { + case IS_NULL: + case IS_LONG: + case IS_DOUBLE: + case IS_STRING: + case IS_ARRAY: + ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == opline->extended_value); + break; + case _IS_BOOL: + ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE); + break; + case IS_OBJECT: + if (Z_TYPE_P(value) == opline->extended_value) { + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } else { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } + break; + case IS_RESOURCE: + if (Z_TYPE_P(value) == opline->extended_value) { + const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value) TSRMLS_CC); + ZVAL_BOOL(EX_VAR(opline->result.var), type_name != NULL); + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } + break; + EMPTY_SWITCH_DEFAULT_CASE() } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); + fast_add_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; - zval *property; - zval *retval; - zval *zptr; SAVE_OPLINE(); - object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - property = opline->op2.zv; - retval = EX_VAR(opline->result.var); - - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (IS_CV != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } + fast_sub_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } +static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - /* here we are sure we are dealing with an object */ - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + SAVE_OPLINE(); + fast_mul_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } else { - zval rv; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); +static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - incdec_op(z); - ZVAL_COPY_VALUE(retval, z); - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - SELECTIVE_PZVAL_LOCK(retval, opline); - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); - } - } - } + SAVE_OPLINE(); + fast_div_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_CV_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_CV_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; - zval *property; - zval *retval; - zval *zptr; SAVE_OPLINE(); - object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - property = opline->op2.zv; - retval = EX_VAR(opline->result.var); - - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (IS_CV != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } - - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); + fast_mod_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - ZVAL_NULL(retval); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - /* here we are sure we are dealing with an object */ +static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - ZVAL_DEREF(zptr); - ZVAL_COPY_VALUE(retval, zptr); - zval_opt_copy_ctor(zptr); + SAVE_OPLINE(); + shift_left_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - incdec_op(zptr); - } else { - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval rv; - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - zval z_copy; - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } - ZVAL_DUP(retval, z); - ZVAL_DUP(&z_copy, z); - incdec_op(&z_copy); - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - zval_ptr_dtor(&z_copy); - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - ZVAL_NULL(retval); - } - } +static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + shift_right_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_post_incdec_property_helper_SPEC_CV_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + USE_OPLINE -static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_post_incdec_property_helper_SPEC_CV_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + + SAVE_OPLINE(); + concat_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varname; - zval *retval; - zend_string *name; - HashTable *target_symbol_table; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - zend_string_addref(name); - } else { - name = zval_get_string(varname); - } + fast_is_identical_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - if (IS_CONST != IS_UNUSED) { - zend_class_entry *ce; - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - if (IS_CV != IS_CONST) { - zend_string_release(name); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); +static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - retval = zend_hash_find(target_symbol_table, name); - if (retval == NULL) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1 TSRMLS_CC); - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + zval *result = EX_VAR(opline->result.var); - } - } + SAVE_OPLINE(); + fast_is_not_identical_function(result, + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - if (IS_CV != IS_CONST) { - zend_string_release(name); - } - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { - ZVAL_UNREF(retval); - } - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + USE_OPLINE -static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + zval *result = EX_VAR(opline->result.var); -static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + SAVE_OPLINE(); + fast_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_not_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + USE_OPLINE + + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_is_smaller_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + USE_OPLINE + + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_is_smaller_or_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + bitwise_or_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *container; - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + SAVE_OPLINE(); + bitwise_and_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *container; - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + SAVE_OPLINE(); + bitwise_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + boolean_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op1; + zend_free_op free_op_data1; + zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + zval *property = opline->op2.zv; + zval *value; + zval *zptr; - SAVE_OPLINE(); + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - } else { - if (IS_CONST == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + + FREE_OP(free_op_data1); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); } - container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + } else { + /* here we are sure we are dealing with an object */ + if (opline->extended_value == ZEND_ASSIGN_OBJ + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { + zval *z = NULL; + zval rv; + + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv TSRMLS_CC); + } + } + if (z) { + if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + } + ZVAL_COPY_VALUE(z, value); + } +//??? if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + SEPARATE_ZVAL_IF_NOT_REF(z); + binary_op(z, z, value TSRMLS_CC); + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), z); + } + zval_ptr_dtor(z); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + FREE_OP(free_op_data1); } + + /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *container; + zend_free_op free_op_data1; + zval *var_ptr, rv; + zval *value, *container; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - + container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - ZVAL_DEREF(container); - zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CV == IS_VAR && !0) { + Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + zval *dim = opline->op2.zv; - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } + if (UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + } + + if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + binary_op(var_ptr, var_ptr, value TSRMLS_CC); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + } + + FREE_OP(free_op_data1); + CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - - zval *offset; + zval *var_ptr; + zval *value; SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - offset = opline->op2.zv; - - if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; + value = opline->op2.zv; + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - /* here we are sure we are dealing with an object */ - do { - if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + } - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } @@ -35116,737 +29271,653 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *property; - zval *container; - SAVE_OPLINE(); - property = opline->op2.zv; - - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *property; - zval *container; - - SAVE_OPLINE(); - property = opline->op2.zv; - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = opline->op2.zv; - - if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1; - zval *property; + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - SAVE_OPLINE(); - property = opline->op2.zv; - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } else { - return ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *container, *property; + + zval *object; + zval *property; + zval *retval; + zval *zptr; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); property = opline->op2.zv; + retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); -static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(retval); + } - zval *container; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } - SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + /* here we are sure we are dealing with an object */ - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - ZVAL_COPY(EX_VAR(opline->result.var), value); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) && - EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) { - zval *result = EX_VAR(opline->result.var); - zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, opline->op2.zv, BP_VAR_R, result TSRMLS_CC); + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { + zval rv; - if (retval) { - if (result != retval) { - ZVAL_COPY(result, retval); + if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + } + ZVAL_COPY_VALUE(z, value); } + if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + SEPARATE_ZVAL_IF_NOT_REF(z); + incdec_op(z); + ZVAL_COPY_VALUE(retval, z); + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + SELECTIVE_PZVAL_LOCK(retval, opline); + zval_ptr_dtor(z); } else { - ZVAL_NULL(result); + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(retval); + } } - } else { - ZVAL_NULL(EX_VAR(opline->result.var)); } + + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_pre_incdec_property_helper_SPEC_CV_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_pre_incdec_property_helper_SPEC_CV_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; - zval *property_name; + zval *property; + zval *retval; + zval *zptr; SAVE_OPLINE(); - object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - property_name = opline->op2.zv; + object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = opline->op2.zv; + retval = EX_VAR(opline->result.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - - - /* assign_obj has two opcodes! */ - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); -} -static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - zval *object_ptr; + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - SAVE_OPLINE(); - object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + ZVAL_NULL(retval); - if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } - ZVAL_DEREF(object_ptr); - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - zval *property_name = opline->op2.zv; + /* here we are sure we are dealing with an object */ - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - } else { - zend_free_op free_op_data1; - zval rv; - zval *value; - zval *dim = opline->op2.zv; - zval *variable_ptr; + ZVAL_DEREF(zptr); + ZVAL_COPY_VALUE(retval, zptr); + zval_opt_copy_ctor(zptr); - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && - EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + incdec_op(zptr); + } else { + if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { + zval rv; + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval z_copy; - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - FREE_OP(free_op_data1); - } else { - zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - variable_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); - if ((opline+1)->op1_type == IS_VAR) { - FREE_OP(free_op_data1); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); } + ZVAL_COPY_VALUE(z, value); } + ZVAL_DUP(retval, z); + ZVAL_DUP(&z_copy, z); + incdec_op(&z_copy); + if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + zval_ptr_dtor(&z_copy); + zval_ptr_dtor(z); + } else { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); + ZVAL_NULL(retval); } } - /* assign_dim has two opcodes! */ + CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = opline->op2.zv; - variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_CONST == IS_TMP_VAR) { - - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CONST TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + return zend_post_incdec_property_helper_SPEC_CV_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); +static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_post_incdec_property_helper_SPEC_CV_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; + zval *varname; + zval *retval; + zend_string *name; + HashTable *target_symbol_table; SAVE_OPLINE(); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - function_name = opline->op2.zv; - - if (IS_CONST != IS_CONST && - UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + if (IS_CV == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + zend_string_addref(name); + } else { + name = zval_get_string(varname); } - object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + if (IS_CONST != IS_UNUSED) { + zend_class_entry *ce; + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + if (IS_CV != IS_CONST) { + zend_string_release(name); + } - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); } + retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL) { - nesting--; + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + retval = zend_hash_find(target_symbol_table, name); + if (retval == NULL) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } } - } while (nesting); + } + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { + if (Z_CONSTANT_P(retval)) { + zval_update_constant(retval, 1 TSRMLS_CC); + } + } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); } + } - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; + if (IS_CV != IS_CONST) { + zend_string_release(name); + } + + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); } - ZEND_VM_JMP(++opline); + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - obj = Z_OBJ_P(object); - called_scope = obj->ce; +static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - if (IS_CONST != IS_CONST || - EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { - zend_object *orig_obj = obj; +static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); - } +static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(obj == orig_obj)) { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); - } - } +static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - GC_REFCOUNT(obj)++; /* For $this pointer */ + return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - +static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); +static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *result = EX_VAR(opline->result.var); + zval *container; SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *expr_ptr, new_expr; + zend_free_op free_op1; + zval *container; SAVE_OPLINE(); - if ((IS_CV == IS_VAR || IS_CV == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); - } - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); - - } else { - expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } else if (IS_CV == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(expr_ptr)) { - expr_ptr = Z_REFVAL_P(expr_ptr); - if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (IS_CONST != IS_UNUSED) { - - zval *offset = opline->op2.zv; - zend_string *str; - zend_ulong hval; - -add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; - } - - } else { - zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE + zend_free_op free_op1; + zval *container; - array = EX_VAR(opline->result.var); - if (IS_CV != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_NEW_ARR(array); - zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV != IS_UNUSED) { - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init(Z_ARRVAL_P(array), 0); - } + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); + zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (IS_CV == IS_UNUSED) { - ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_CV != IS_UNUSED - } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#endif + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval tmp, *varname; - HashTable *target_symbol_table; + zval *container; SAVE_OPLINE(); - if (IS_CV == IS_CV && - IS_CONST == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - zval *var = EX_VAR(opline->op1.var); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (Z_REFCOUNTED_P(var)) { - zend_refcounted *garbage = Z_COUNTED_P(var); - if (!--GC_REFCOUNT(garbage)) { - ZVAL_UNDEF(var); - _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); - } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); - } - } else { - ZVAL_UNDEF(var); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zend_free_op free_op1; - ZVAL_UNDEF(&tmp); - if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } + SAVE_OPLINE(); - if (IS_CONST != IS_UNUSED) { - zend_class_entry *ce; + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); - } + if (IS_CONST == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op1; zval *container; - zval *offset; - zend_ulong hval; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - if (IS_CV != IS_UNUSED) { - ZVAL_DEREF(container); + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - SEPARATE_ZVAL_NOREF(container); - offset = opline->op2.zv; - - if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); -offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); - } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CONST == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { + ZVAL_DEREF(container); + zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; + zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - offset = opline->op2.zv; + container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + offset = opline->op2.zv; - if (IS_CV != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->unset_property) { - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to unset property of non-object"); - } + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; + + /* here we are sure we are dealing with an object */ + do { + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); + + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } + } + + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } while (0); } @@ -35854,1488 +29925,1443 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; + zend_free_op free_op1; + zval *property; + zval *container; SAVE_OPLINE(); - if (IS_CV == IS_CV && - IS_CONST == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - value = EX_VAR(opline->op1.var); - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !i_zend_is_true(value TSRMLS_CC)); - CHECK_EXCEPTION(); - } - ZEND_VM_NEXT_OPCODE(); - } else { - - zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + property = opline->op2.zv; - ZVAL_UNDEF(&tmp); - if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } - if (IS_CONST != IS_UNUSED) { - zend_class_entry *ce; + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); - } + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } - if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - value && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !value || !i_zend_is_true(value TSRMLS_CC)); - } +static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *property; + zval *container; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + SAVE_OPLINE(); + property = opline->op2.zv; + container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); + + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; - int result; - zend_ulong hval; + zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = opline->op2.zv; + offset = opline->op2.zv; - if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); - zval *value; - zend_string *str; + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; + /* here we are sure we are dealing with an object */ + do { + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); + + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } } } -str_index_prop: - value = zend_hash_find_ind(ht, str); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - value = NULL; - break; - } - } - if (opline->extended_value & ZEND_ISSET) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); - } - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { - result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check element of non-array"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ - zval tmp; + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - result = 0; - if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - ZVAL_DEREF(offset); - } - if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ - || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ - && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { - ZVAL_DUP(&tmp, offset); - convert_to_long(&tmp); - offset = &tmp; - } - } - if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { - if ((opline->extended_value & ZEND_ISSET) || - Z_STRVAL_P(container)[offset->value.lval] != '0') { - result = 1; - } + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); } - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + } while (0); } - ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - int result; - zval *offset; - SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = opline->op2.zv; + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + /* Behave like FETCH_OBJ_W */ + zend_free_op free_op1; + zval *property; - if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; + SAVE_OPLINE(); + property = opline->op2.zv; + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + return ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - ZVAL_BOOL(EX_VAR(opline->result.var), result); +static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container, *property; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + property = opline->op2.zv; + + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; - zend_bool result; + zval *container; SAVE_OPLINE(); - expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); + zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + ZVAL_COPY(EX_VAR(opline->result.var), value); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) && + EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) { + zval *result = EX_VAR(opline->result.var); + zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, opline->op2.zv, BP_VAR_R, result TSRMLS_CC); + + if (retval) { + if (result != retval) { + ZVAL_COPY(result, retval); } } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); + ZVAL_NULL(result); } - result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); } else { - result = 0; + ZVAL_NULL(EX_VAR(opline->result.var)); } - ZVAL_BOOL(EX_VAR(opline->result.var), result); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - /* The generator object is stored in EX(return_value) */ - zend_generator *generator = (zend_generator *) EX(return_value); + zval *object; + zval *property_name; - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + SAVE_OPLINE(); + object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + property_name = opline->op2.zv; + + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); + /* assign_obj has two opcodes! */ + CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); +} - /* Set the new yielded value */ - if (IS_CV != IS_UNUSED) { +static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zval *value; + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + zval *property_name = opline->op2.zv; - /* Temporary variables don't need ctor copying */ - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); - } - } else { - zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); - } + } else { + zend_free_op free_op_data1; + zval rv; + zval *value; + zval *dim = opline->op2.zv; + zval *variable_ptr; - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - } else { - ZVAL_MAKE_REF(value_ptr); - } - ZVAL_COPY(&generator->value, value_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - } + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->value, value); - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + FREE_OP(free_op_data1); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); } - /* Set the new yielded key */ - if (IS_CONST != IS_UNUSED) { + /* assign_dim has two opcodes! */ + CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); +} - zval *key = opline->op2.zv; +static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->key, key); - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + zval *value; + zval *variable_ptr; - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } + SAVE_OPLINE(); + value = opline->op2.zv; + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); + if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_CONST == IS_TMP_VAR) { + + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CONST TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; } - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); + /* zend_assign_to_variable() always takes care of op2, never free it! */ - ZEND_VM_RETURN(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; SAVE_OPLINE(); - pow_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - opline->op2.zv TSRMLS_CC); + function_name = opline->op2.zv; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Method name must be a string"); + } -static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_binary_assign_op_helper_SPEC_CV_CONST(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); -static int ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; - zval *varname; - zval *value; - zval *variable_ptr; - uint32_t idx; + if (UNEXPECTED(EG(exception) != NULL)) { - SAVE_OPLINE(); - varname = opline->op2.zv; + HANDLE_EXCEPTION(); + } - /* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ - idx = (uint32_t)(uintptr_t)CACHED_PTR(Z_CACHE_SLOT_P(varname)) - 1; - if (EXPECTED(idx < EG(symbol_table).ht.nNumUsed)) { - Bucket *p = EG(symbol_table).ht.arData + idx; + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(varname)) || - (EXPECTED(p->h == Z_STR_P(varname)->h) && - EXPECTED(p->key != NULL) && - EXPECTED(p->key->len == Z_STRLEN_P(varname)) && - EXPECTED(memcmp(p->key->val, Z_STRVAL_P(varname), Z_STRLEN_P(varname)) == 0)))) { - value = &EG(symbol_table).ht.arData[idx].val; - goto check_indirect; + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); + } + + obj = Z_OBJ_P(object); + called_scope = obj->ce; + + if (IS_CONST != IS_CONST || + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { + zend_object *orig_obj = obj; + + if (UNEXPECTED(obj->handlers->get_method == NULL)) { + zend_error_noreturn(E_ERROR, "Object does not support method calls"); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + } + if (IS_CONST == IS_CONST && + EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); } } - value = zend_hash_find(&EG(symbol_table).ht, Z_STR_P(varname)); - if (UNEXPECTED(value == NULL)) { - value = zend_hash_add_new(&EG(symbol_table).ht, Z_STR_P(varname), &EG(uninitialized_zval)); - idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket); - /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ - CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)(idx + 1)); + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + obj = NULL; } else { - idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket); - /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ - CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)(idx + 1)); -check_indirect: - /* GLOBAL variable may be an INDIRECT pointer to CV */ - if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) { - value = Z_INDIRECT_P(value); - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - ZVAL_NULL(value); - } - } + GC_REFCOUNT(obj)++; /* For $this pointer */ } - variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - zend_assign_to_variable_reference(variable_ptr, value TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - fast_mod_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + fast_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - SAVE_OPLINE(); - shift_left_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval *expr_ptr, new_expr; - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + SAVE_OPLINE(); + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && + (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + } + ZVAL_MAKE_REF(expr_ptr); + Z_ADDREF_P(expr_ptr); -static int ZEND_FASTCALL ZEND_SR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; + } else { + expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } else if (IS_CV == IS_CONST) { + if (!Z_IMMUTABLE_P(expr_ptr)) { + ZVAL_DUP(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } + } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(expr_ptr)) { + expr_ptr = Z_REFVAL_P(expr_ptr); + if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); - SAVE_OPLINE(); - shift_right_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (IS_CONST != IS_UNUSED) { -static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; + zval *offset = opline->op2.zv; + zend_string *str; + zend_ulong hval; - SAVE_OPLINE(); - concat_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); +add_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index; + case IS_FALSE: + hval = 0; + goto num_index; + case IS_TRUE: + hval = 1; + goto num_index; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto add_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); + /* do nothing */ + break; + } - zval_ptr_dtor_nogc(free_op2); + } else { + zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zval *array; + uint32_t size; USE_OPLINE - zend_free_op free_op2; - SAVE_OPLINE(); - fast_is_identical_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + array = EX_VAR(opline->result.var); + if (IS_CV != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + } else { + size = 0; + } + ZVAL_NEW_ARR(array); + zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (IS_CV != IS_UNUSED) { + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init(Z_ARRVAL_P(array), 0); + } + } + + if (IS_CV == IS_UNUSED) { + ZEND_VM_NEXT_OPCODE(); +#if 0 || IS_CV != IS_UNUSED + } else { + return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +#endif + } } -static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *result = EX_VAR(opline->result.var); + zval tmp, *varname; + HashTable *target_symbol_table; + SAVE_OPLINE(); - fast_is_not_identical_function(result, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + if (IS_CV == IS_CV && + IS_CONST == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + zval *var = EX_VAR(opline->op1.var); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (Z_REFCOUNTED_P(var)) { + zend_refcounted *garbage = Z_COUNTED_P(var); -static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; + if (!--GC_REFCOUNT(garbage)) { + ZVAL_UNDEF(var); + _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); + } else { + GC_ZVAL_CHECK_POSSIBLE_ROOT(var); + ZVAL_UNDEF(var); + } + } else { + ZVAL_UNDEF(var); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } - SAVE_OPLINE(); - bitwise_or_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + ZVAL_UNDEF(&tmp); + if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } -static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; + if (IS_CONST != IS_UNUSED) { + zend_class_entry *ce; - SAVE_OPLINE(); - bitwise_and_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); + } + + if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + + zval *container; + zval *offset; + zend_ulong hval; SAVE_OPLINE(); - bitwise_xor_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + SEPARATE_ZVAL_NOREF(container); + offset = opline->op2.zv; - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); +offset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; + } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } -static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_CONST == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - SAVE_OPLINE(); - boolean_xor_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + + } - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data1; - zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - zval *value; - zval *zptr; - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zval *container; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } + offset = opline->op2.zv; if (IS_CV != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); + ZVAL_DEREF(container); } - - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - zval_ptr_dtor_nogc(free_op2); - FREE_OP(free_op_data1); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - /* here we are sure we are dealing with an object */ - if (opline->extended_value == ZEND_ASSIGN_OBJ - && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->unset_property) { + Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { - zval *z = NULL; - zval rv; - - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - } - } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv TSRMLS_CC); - } - } - if (z) { - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } -//??? if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - binary_op(z, z, value TSRMLS_CC); - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), z); - } - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } + zend_error(E_NOTICE, "Trying to unset property of non-object"); } - - zval_ptr_dtor_nogc(free_op2); - FREE_OP(free_op_data1); } - /* assign_obj has two opcodes! */ + CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data1; - zval *var_ptr, rv; - zval *value, *container; + zval *value; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - if (IS_CV != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_CV == IS_VAR && !0) { - Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + if (IS_CV == IS_CV && + IS_CONST == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + ZEND_VM_NEXT_OPCODE(); } else { - zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - } + zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } + ZVAL_UNDEF(&tmp); + if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } - if (UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + if (IS_CONST != IS_UNUSED) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - binary_op(var_ptr, var_ptr, value TSRMLS_CC); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); } - } - zval_ptr_dtor_nogc(free_op2); - FREE_OP(free_op_data1); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); + } - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *var_ptr; - zval *value; + + zval *container; + int result; + zend_ulong hval; + zval *offset; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = opline->op2.zv; - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value; + zend_string *str; - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } +str_index_prop: + value = zend_hash_find_ind(ht, str); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else { + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 1; + goto num_index_prop; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto isset_again; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + value = NULL; + break; + } } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - binary_op(var_ptr, var_ptr, value TSRMLS_CC); + if (opline->extended_value & ZEND_ISSET) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check element of non-array"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ + zval tmp; - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(offset); + } + if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ + || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ + && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { + ZVAL_DUP(&tmp, offset); + convert_to_long(&tmp); + offset = &tmp; + } + } + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { + if ((opline->extended_value & ZEND_ISSET) || + Z_STRVAL_P(container)[offset->value.lval] != '0') { + result = 1; + } + } + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_ptr_dtor_nogc(free_op2); + ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + zval *container; + int result; + zval *offset; -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); + container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = opline->op2.zv; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); } -} -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + ZVAL_BOOL(EX_VAR(opline->result.var), result); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + zval *expr; + zend_bool result; -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); + expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + ZVAL_BOOL(EX_VAR(opline->result.var), result); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + /* The generator object is stored in EX(return_value) */ + zend_generator *generator = (zend_generator *) EX(return_value); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { -static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *object; - zval *property; - zval *retval; - zval *zptr; - SAVE_OPLINE(); - object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - retval = EX_VAR(opline->result.var); + if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value; - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - if (IS_CV != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); - } + /* Temporary variables don't need ctor copying */ + if (IS_CV != IS_TMP_VAR) { + zval_opt_copy_ctor(&generator->value); + } + } else { + zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } - /* here we are sure we are dealing with an object */ + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + } else { + ZVAL_MAKE_REF(value_ptr); + } + ZVAL_COPY(&generator->value, value_ptr); - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST) { + ZVAL_DUP(&generator->value, value); + } else if (IS_CV == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { + ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } } } else { - zval rv; + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST) { + ZVAL_DUP(&generator->key, key); + } else if (IS_CONST == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->key, key); + } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { + ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); - } - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - incdec_op(z); - ZVAL_COPY_VALUE(retval, z); - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - SELECTIVE_PZVAL_LOCK(retval, opline); - zval_ptr_dtor(z); } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); + ZVAL_COPY_VALUE(&generator->key, key); + if (IS_CONST == IS_CV) { + if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); } } + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); } - zval_ptr_dtor_nogc(free_op2); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); -static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_CV_TMP(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); -static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_CV_TMP(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + ZEND_VM_RETURN(); } -static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *object; - zval *property; - zval *retval; - zval *zptr; + SAVE_OPLINE(); - object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - retval = EX_VAR(opline->result.var); + pow_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + opline->op2.zv TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - if (IS_CV != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); - ZVAL_NULL(retval); +static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper_SPEC_CV_CONST(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } +static int ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - /* here we are sure we are dealing with an object */ + zval *varname; + zval *value; + zval *variable_ptr; + uint32_t idx; - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + SAVE_OPLINE(); + varname = opline->op2.zv; - ZVAL_DEREF(zptr); - ZVAL_COPY_VALUE(retval, zptr); - zval_opt_copy_ctor(zptr); + /* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ + idx = (uint32_t)(uintptr_t)CACHED_PTR(Z_CACHE_SLOT_P(varname)) - 1; + if (EXPECTED(idx < EG(symbol_table).ht.nNumUsed)) { + Bucket *p = EG(symbol_table).ht.arData + idx; - incdec_op(zptr); - } else { - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval rv; - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - zval z_copy; + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && + (EXPECTED(p->key == Z_STR_P(varname)) || + (EXPECTED(p->h == Z_STR_P(varname)->h) && + EXPECTED(p->key != NULL) && + EXPECTED(p->key->len == Z_STRLEN_P(varname)) && + EXPECTED(memcmp(p->key->val, Z_STRVAL_P(varname), Z_STRLEN_P(varname)) == 0)))) { - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + value = &EG(symbol_table).ht.arData[idx].val; + goto check_indirect; + } + } - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); + value = zend_hash_find(&EG(symbol_table).ht, Z_STR_P(varname)); + if (UNEXPECTED(value == NULL)) { + value = zend_hash_add_new(&EG(symbol_table).ht, Z_STR_P(varname), &EG(uninitialized_zval)); + idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket); + /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ + CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)(idx + 1)); + } else { + idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket); + /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ + CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)(idx + 1)); +check_indirect: + /* GLOBAL variable may be an INDIRECT pointer to CV */ + if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) { + value = Z_INDIRECT_P(value); + if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + ZVAL_NULL(value); } - ZVAL_DUP(retval, z); - ZVAL_DUP(&z_copy, z); - incdec_op(&z_copy); - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - zval_ptr_dtor(&z_copy); - zval_ptr_dtor(z); - } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - ZVAL_NULL(retval); } } - zval_ptr_dtor_nogc(free_op2); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + zend_assign_to_variable_reference(variable_ptr, value TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_post_incdec_property_helper_SPEC_CV_TMP(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_post_incdec_property_helper_SPEC_CV_TMP(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + fast_mod_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container; + zend_free_op free_op2; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + shift_left_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container; + zend_free_op free_op2; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + shift_right_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + concat_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op1, free_op2; + zend_free_op free_op2; SAVE_OPLINE(); + fast_is_identical_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - zval_ptr_dtor_nogc(free_op2); - - } else { - if (IS_TMP_VAR == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - - } + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container; + zend_free_op free_op2; + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + fast_is_not_identical_function(result, + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *container; zend_free_op free_op2; - zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - - if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_TMP_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); - } + bitwise_or_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *property; - zval *container; + zend_free_op free_op2; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } + bitwise_and_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *property; - zval *container; + zend_free_op free_op2; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + bitwise_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *container; zend_free_op free_op2; - zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - - if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; - - /* here we are sure we are dealing with an object */ - do { - if (IS_TMP_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); - - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } - - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); - } + boolean_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; + zend_free_op free_op2, free_op_data1; + zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zval *value; + zval *zptr; - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1, free_op2; - zval *property; + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } - SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } + FREE_OP(free_op_data1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } } else { - return ZEND_FETCH_OBJ_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container, *property; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + /* here we are sure we are dealing with an object */ + if (opline->extended_value == ZEND_ASSIGN_OBJ + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_TMP_VAR, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { + zval *z = NULL; + zval rv; -static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *object; - zval *property_name; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv TSRMLS_CC); + } + } + if (z) { + if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); - SAVE_OPLINE(); - object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + } + ZVAL_COPY_VALUE(z, value); + } +//??? if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + SEPARATE_ZVAL_IF_NOT_REF(z); + binary_op(z, z, value TSRMLS_CC); + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), z); + } + zval_ptr_dtor(z); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); @@ -37343,599 +31369,465 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *object_ptr; + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; + zval *value, *container; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { + container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - ZVAL_DEREF(object_ptr); - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - zend_free_op free_op2; - zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CV == IS_VAR && !0) { + Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zend_free_op free_op2, free_op_data1; - zval rv; - zval *value; zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - zval *variable_ptr; - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && - EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - FREE_OP(free_op_data1); - } else { - zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - variable_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); - if ((opline+1)->op1_type == IS_VAR) { - FREE_OP(free_op_data1); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - } + zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); + } + + if (UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + } + + if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + binary_op(var_ptr, var_ptr, value TSRMLS_CC); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } } - /* assign_dim has two opcodes! */ + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); + CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; + zval *var_ptr; zval *value; - zval *variable_ptr; SAVE_OPLINE(); value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_VAR == IS_TMP_VAR) { - zval_ptr_dtor_nogc(free_op2); - } - if (RETURN_VALUE_USED(opline)) { + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + } + + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + binary_op(var_ptr, var_ptr, value TSRMLS_CC); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; - zend_free_op free_op2; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; - SAVE_OPLINE(); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (IS_TMP_VAR != IS_CONST && - UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); - } +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - zval_ptr_dtor_nogc(free_op2); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL) { - nesting--; - } - } while (nesting); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - obj = Z_OBJ_P(object); - called_scope = obj->ce; +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (IS_TMP_VAR != IS_CONST || - EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { - zend_object *orig_obj = obj; + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); - } +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_TMP_VAR == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(obj == orig_obj)) { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); - } + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; - } else { - GC_REFCOUNT(obj)++; /* For $this pointer */ +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - zval_ptr_dtor_nogc(free_op2); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *result = EX_VAR(opline->result.var); + zval *container; SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *expr_ptr, new_expr; + zend_free_op free_op1, free_op2; + zval *container; SAVE_OPLINE(); - if ((IS_CV == IS_VAR || IS_CV == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); - } - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); - - } else { - expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } else if (IS_CV == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(expr_ptr)) { - expr_ptr = Z_REFVAL_P(expr_ptr); - if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - zend_string *str; - zend_ulong hval; - -add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; - } - zval_ptr_dtor_nogc(free_op2); - } else { - zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; - array = EX_VAR(opline->result.var); - if (IS_CV != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_NEW_ARR(array); - zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV != IS_UNUSED) { - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init(Z_ARRVAL_P(array), 0); - } + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (IS_CV == IS_UNUSED) { - ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_CV != IS_UNUSED - } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#endif + ZVAL_DEREF(container); + zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; zval *container; - zval *offset; - zend_ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - if (IS_CV != IS_UNUSED) { - ZVAL_DEREF(container); - } - SEPARATE_ZVAL_NOREF(container); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); - if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); -offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); - } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zend_free_op free_op1, free_op2; + + SAVE_OPLINE(); + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zval_ptr_dtor_nogc(free_op2); - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } -//??? if (IS_TMP_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + if (IS_TMP_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - } + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zend_free_op free_op1, free_op2; zval *container; - zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - if (IS_CV != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->unset_property) { - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to unset property of non-object"); - } + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); + zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *container; - int result; - zend_ulong hval; - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); - zval *value; - zend_string *str; + zval *object_ptr; -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } - } -str_index_prop: - value = zend_hash_find_ind(ht, str); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - value = NULL; - break; - } - } + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (opline->extended_value & ZEND_ISSET) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); - } - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { - result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check element of non-array"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ - zval tmp; + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); - result = 0; - if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(offset); - } - if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ - || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ - && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { - ZVAL_DUP(&tmp, offset); - convert_to_long(&tmp); - offset = &tmp; - } - } - if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { - if ((opline->extended_value & ZEND_ISSET) || - Z_STRVAL_P(container)[offset->value.lval] != '0') { - result = 1; + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + } else { + zend_free_op free_op2, free_op_data1; + zval rv; + zval *value; + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + zval *variable_ptr; + + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); + } else { + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + FREE_OP(free_op_data1); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - + /* assign_dim has two opcodes! */ CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *container; - int result; - zval *offset; + zval *value; + zval *variable_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; + if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_VAR == IS_TMP_VAR) { + zval_ptr_dtor_nogc(free_op2); } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); + /* zend_assign_to_variable() always takes care of op2, never free it! */ CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -38330,456 +32222,855 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina FREE_OP(free_op_data1); } - /* assign_obj has two opcodes! */ + /* assign_obj has two opcodes! */ + CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; + zval *value, *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CV == IS_VAR && !0) { + Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + + zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); + } + + if (UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + } + + if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + binary_op(var_ptr, var_ptr, value TSRMLS_CC); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + } + + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); + + CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *var_ptr; + zval *value; + + SAVE_OPLINE(); + value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + } + + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + binary_op(var_ptr, var_ptr, value TSRMLS_CC); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + } + + zval_ptr_dtor_nogc(free_op2); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *varname; + zval *retval; + zend_string *name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + zend_string_addref(name); + } else { + name = zval_get_string(varname); + } + + if (IS_VAR != IS_UNUSED) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + if (IS_CV != IS_CONST) { + zend_string_release(name); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + retval = zend_hash_find(target_symbol_table, name); + if (retval == NULL) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } + } + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { + if (Z_CONSTANT_P(retval)) { + zval_update_constant(retval, 1 TSRMLS_CC); + } + } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + + } + } + + if (IS_CV != IS_CONST) { + zend_string_release(name); + } + + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data1; - zval *var_ptr, rv; - zval *value, *container; + zend_free_op free_op1, free_op2; + zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (IS_CV != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_CV == IS_VAR && !0) { - Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ - } - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); - - zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); +static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; - binary_op(var_ptr, var_ptr, value TSRMLS_CC); + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - + ZVAL_DEREF(container); + zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2); - FREE_OP(free_op_data1); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *var_ptr; - zval *value; + zval *container; SAVE_OPLINE(); - value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); - var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zend_free_op free_op1, free_op2; - binary_op(var_ptr, var_ptr, value TSRMLS_CC); + SAVE_OPLINE(); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op2); + } else { + if (IS_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(container); + zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + zval *object_ptr; -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } -} + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + } else { + zend_free_op free_op2, free_op_data1; + zval rv; + zval *value; + zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + zval *variable_ptr; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); + } else { + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + FREE_OP(free_op_data1); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } } + + /* assign_dim has two opcodes! */ + CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op2; + zval *value; + zval *variable_ptr; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + SAVE_OPLINE(); + value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_VAR == IS_TMP_VAR) { + zval_ptr_dtor_nogc(free_op2); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -} -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + /* zend_assign_to_variable() always takes care of op2, never free it! */ + zval_ptr_dtor_nogc(free_op2); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op2; + zval *variable_ptr; + zval *value_ptr; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + SAVE_OPLINE(); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2); -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + if (!(free_op2 != NULL)) { + PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ + } + zend_error(E_STRICT, "Only variables should be assigned by reference"); + if (UNEXPECTED(EG(exception) != NULL)) { + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + HANDLE_EXCEPTION(); + } + return ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { + if (!(free_op2 != NULL)) { + PZVAL_LOCK(value_ptr); + } + } - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } + if (IS_CV == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(variable_ptr))) { + zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); + } + if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || + (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { + variable_ptr = &EG(uninitialized_zval); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr TSRMLS_CC); } -} -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { + if (!(free_op2 != NULL)) { + Z_DELREF_P(variable_ptr); + } + } - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } -} -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *object; - zval *property; - zval *retval; - zval *zptr; + zval tmp, *varname; + HashTable *target_symbol_table; - SAVE_OPLINE(); - object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } + SAVE_OPLINE(); + if (IS_CV == IS_CV && + IS_VAR == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + zval *var = EX_VAR(opline->op1.var); - if (IS_CV != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } + if (Z_REFCOUNTED_P(var)) { + zend_refcounted *garbage = Z_COUNTED_P(var); - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); + if (!--GC_REFCOUNT(garbage)) { + ZVAL_UNDEF(var); + _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); + } else { + GC_ZVAL_CHECK_POSSIBLE_ROOT(var); + ZVAL_UNDEF(var); + } + } else { + ZVAL_UNDEF(var); } - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - /* here we are sure we are dealing with an object */ - - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } else { - zval rv; + ZVAL_UNDEF(&tmp); + if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + zend_class_entry *ce; - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + HANDLE_EXCEPTION(); } - ZVAL_COPY_VALUE(z, value); + if (UNEXPECTED(ce == NULL)) { + zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); } - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - incdec_op(z); - ZVAL_COPY_VALUE(retval, z); - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - SELECTIVE_PZVAL_LOCK(retval, opline); - zval_ptr_dtor(z); } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(retval); - } + ce = Z_CE_P(EX_VAR(opline->op2.var)); } + zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } - zval_ptr_dtor_nogc(free_op2); + if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_CV_VAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_pre_incdec_property_helper_SPEC_CV_VAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *object; - zval *property; - zval *retval; - zval *zptr; + zval *value; SAVE_OPLINE(); - object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - retval = EX_VAR(opline->result.var); - - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - - if (IS_CV != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ - } - - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_ptr_dtor_nogc(free_op2); - ZVAL_NULL(retval); - - CHECK_EXCEPTION(); + if (IS_CV == IS_CV && + IS_VAR == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); + } ZEND_VM_NEXT_OPCODE(); - } - - /* here we are sure we are dealing with an object */ - - if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + } else { - ZVAL_DEREF(zptr); - ZVAL_COPY_VALUE(retval, zptr); - zval_opt_copy_ctor(zptr); + zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - incdec_op(zptr); - } else { - if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval rv; - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - zval z_copy; + ZVAL_UNDEF(&tmp); + if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + zend_class_entry *ce; - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); } - ZVAL_COPY_VALUE(z, value); + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); } - ZVAL_DUP(retval, z); - ZVAL_DUP(&z_copy, z); - incdec_op(&z_copy); - if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - zval_ptr_dtor(&z_copy); - zval_ptr_dtor(z); + value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - ZVAL_NULL(retval); + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } - } - - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } -static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_post_incdec_property_helper_SPEC_CV_VAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); + } -static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_post_incdec_property_helper_SPEC_CV_VAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } -static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varname; - zval *retval; - zend_string *name; - HashTable *target_symbol_table; + zval *expr; + zend_bool result; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - zend_string_addref(name); - } else { - name = zval_get_string(varname); - } + expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (IS_VAR != IS_UNUSED) { + if (Z_TYPE_P(expr) == IS_OBJECT) { zend_class_entry *ce; if (IS_VAR == IS_CONST) { if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); if (UNEXPECTED(ce == NULL)) { - if (IS_CV != IS_CONST) { - zend_string_release(name); - } + ZVAL_FALSE(EX_VAR(opline->result.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -38789,767 +33080,785 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN } else { ce = Z_CE_P(EX_VAR(opline->op2.var)); } - retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - retval = zend_hash_find(target_symbol_table, name); - if (retval == NULL) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1 TSRMLS_CC); - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - - } - } - - if (IS_CV != IS_CONST) { - zend_string_release(name); + result = 0; } + ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { - ZVAL_UNREF(retval); - } - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + USE_OPLINE -static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + /* The generator object is stored in EX(return_value) */ + zend_generator *generator = (zend_generator *) EX(return_value); -static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } -static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); -static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { -static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *container; + if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value; - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); -static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container; + /* Temporary variables don't need ctor copying */ + if (IS_CV != IS_TMP_VAR) { + zval_opt_copy_ctor(&generator->value); + } + } else { + zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + } else { + ZVAL_MAKE_REF(value_ptr); + } + ZVAL_COPY(&generator->value, value_ptr); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); -static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container; + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST) { + ZVAL_DUP(&generator->value, value); + } else if (IS_CV == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { + ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_DUP(&generator->key, key); + } else if (IS_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->key, key); + } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { + ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + zval_ptr_dtor_nogc(free_op2); + } else { + ZVAL_COPY_VALUE(&generator->key, key); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + } + } + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); } - ZVAL_DEREF(container); - zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + pow_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper_SPEC_CV_VAR(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op1, free_op2; + zend_free_op free_op_data1; + zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + zval *property = NULL; + zval *value; + zval *zptr; - SAVE_OPLINE(); + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - zval_ptr_dtor_nogc(free_op2); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + FREE_OP(free_op_data1); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } } else { - if (IS_VAR == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + /* here we are sure we are dealing with an object */ + if (opline->extended_value == ZEND_ASSIGN_OBJ + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { + zval *z = NULL; + zval rv; + + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv TSRMLS_CC); + } + } + if (z) { + if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + } + ZVAL_COPY_VALUE(z, value); + } +//??? if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + SEPARATE_ZVAL_IF_NOT_REF(z); + binary_op(z, z, value TSRMLS_CC); + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), z); + } + zval_ptr_dtor(z); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } } - container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); } + + /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container; + zend_free_op free_op_data1; + zval *var_ptr, rv; + zval *value, *container; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - + container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - ZVAL_DEREF(container); - zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2), IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CV == IS_VAR && !0) { + Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + zval *dim = NULL; + + zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); + } + + if (UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + } + + if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + binary_op(var_ptr, var_ptr, value TSRMLS_CC); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } + FREE_OP(free_op_data1); + CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; - zval *offset; + zval *var_ptr; + zval *value; SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - zend_error(E_NOTICE, "Trying to get property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; + value = NULL; + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - /* here we are sure we are dealing with an object */ - do { - if (IS_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + } - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *property; - zval *container; - - SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *property; - zval *container; - - SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; - zval *offset; + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || - UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - zval *retval; + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - /* here we are sure we are dealing with an object */ - do { - if (IS_VAR == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); - zend_object *zobj = Z_OBJ_P(container); +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (EXPECTED(prop_info)) { - retval = OBJ_PROP(zobj, prop_info->offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; - } - } - } + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } - } while (0); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} - zval_ptr_dtor_nogc(free_op2); +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1, free_op2; - zval *property; - SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } else { - return ZEND_FETCH_OBJ_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *container, *property; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_VAR, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *object; - zval *property_name; - - SAVE_OPLINE(); - object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - - /* assign_obj has two opcodes! */ - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr; + zval *varname; + zval *retval; + zend_string *name; + HashTable *target_symbol_table; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + if (IS_CV == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + zend_string_addref(name); + } else { + name = zval_get_string(varname); } - ZVAL_DEREF(object_ptr); - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - zend_free_op free_op2; - zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - } else { - zend_free_op free_op2, free_op_data1; - zval rv; - zval *value; - zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); - zval *variable_ptr; + if (IS_UNUSED != IS_UNUSED) { + zend_class_entry *ce; - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && - EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - FREE_OP(free_op_data1); - } else { - zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - variable_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } + if (IS_UNUSED == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); - if ((opline+1)->op1_type == IS_VAR) { - FREE_OP(free_op_data1); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + if (IS_CV != IS_CONST) { + zend_string_release(name); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); } - } - - /* assign_dim has two opcodes! */ - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2); - variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_VAR == IS_TMP_VAR) { - zval_ptr_dtor_nogc(free_op2); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } } else { - value = zend_assign_to_variable(variable_ptr, value, IS_VAR TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + retval = zend_hash_find(target_symbol_table, name); + if (retval == NULL) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { + if (Z_CONSTANT_P(retval)) { + zval_update_constant(retval, 1 TSRMLS_CC); + } + } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + } } - /* zend_assign_to_variable() always takes care of op2, never free it! */ - zval_ptr_dtor_nogc(free_op2); + if (IS_CV != IS_CONST) { + zend_string_release(name); + } + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - zend_free_op free_op2; - zval *variable_ptr; - zval *value_ptr; + return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - SAVE_OPLINE(); - value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2); +static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } - if (IS_VAR == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!(free_op2 != NULL)) { - PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ - } - zend_error(E_STRICT, "Only variables should be assigned by reference"); - if (UNEXPECTED(EG(exception) != NULL)) { - if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; - HANDLE_EXCEPTION(); - } - return ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { - if (!(free_op2 != NULL)) { - PZVAL_LOCK(value_ptr); - } - } +static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } - if (IS_CV == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); - } - if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || - (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { - variable_ptr = &EG(uninitialized_zval); +static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr TSRMLS_CC); + return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +} + +static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { - if (!(free_op2 != NULL)) { - Z_DELREF_P(variable_ptr); - } - } +static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; - zend_free_op free_op2; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; + zend_free_op free_op1; + zval *container; SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_VAR != IS_CONST && - UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); + zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); - } +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zend_free_op free_op1; - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - zval_ptr_dtor_nogc(free_op2); + SAVE_OPLINE(); - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL) { - nesting--; - } - } while (nesting); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + if (IS_UNUSED == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - obj = Z_OBJ_P(object); - called_scope = obj->ce; +static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (IS_VAR != IS_CONST || - EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { - zend_object *orig_obj = obj; + zval *object_ptr; - if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); - } + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); - } - if (IS_VAR == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && - EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(obj == orig_obj)) { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); - } + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; - } else { - GC_REFCOUNT(obj)++; /* For $this pointer */ - } + zval *property_name = NULL; - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); + } else { + zend_free_op free_op_data1; + zval rv; + zval *value; + zval *dim = NULL; + zval *variable_ptr; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); -static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *result = EX_VAR(opline->result.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); + } else { + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_UNUSED TSRMLS_CC); - SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + FREE_OP(free_op_data1); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } + } - zval_ptr_dtor_nogc(free_op2); + /* assign_dim has two opcodes! */ CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -39584,9 +33893,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE } } - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if (IS_UNUSED != IS_UNUSED) { + + zval *offset = NULL; zend_string *str; zend_ulong hval; @@ -39602,7 +33911,7 @@ num_index: break; case IS_STRING: str = Z_STR_P(offset); - if (IS_VAR != IS_CONST) { + if (IS_UNUSED != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index; } @@ -39629,7 +33938,7 @@ str_index: /* do nothing */ break; } - zval_ptr_dtor_nogc(free_op2); + } else { zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } @@ -39637,7 +33946,7 @@ str_index: ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -39663,12 +33972,12 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE ZEND_VM_NEXT_OPCODE(); #if 0 || IS_CV != IS_UNUSED } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #endif } } -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval tmp, *varname; @@ -39677,7 +33986,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); if (IS_CV == IS_CV && - IS_VAR == IS_UNUSED && + IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { zval *var = EX_VAR(opline->op1.var); @@ -39706,10 +34015,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER varname = &tmp; } - if (IS_VAR != IS_UNUSED) { + if (IS_UNUSED != IS_UNUSED) { zend_class_entry *ce; - if (IS_VAR == IS_CONST) { + if (IS_UNUSED == IS_CONST) { if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else { @@ -39743,129 +34052,14 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *container; - zval *offset; - zend_ulong hval; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - if (IS_CV != IS_UNUSED) { - ZVAL_DEREF(container); - } - SEPARATE_ZVAL_NOREF(container); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); -offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); - } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2); - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - zval_ptr_dtor_nogc(free_op2); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *container; - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - } - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_CV != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->unset_property) { - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to unset property of non-object"); - } - } - zval_ptr_dtor_nogc(free_op2); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; SAVE_OPLINE(); if (IS_CV == IS_CV && - IS_VAR == IS_UNUSED && + IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { value = EX_VAR(opline->op1.var); if (opline->extended_value & ZEND_ISSET) { @@ -39888,10 +34082,10 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE varname = &tmp; } - if (IS_VAR != IS_UNUSED) { + if (IS_UNUSED != IS_UNUSED) { zend_class_entry *ce; - if (IS_VAR == IS_CONST) { + if (IS_UNUSED == IS_CONST) { if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else { @@ -39929,193 +34123,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE } } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *container; - int result; - zend_ulong hval; - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(container); - zval *value; - zend_string *str; - -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } - } -str_index_prop: - value = zend_hash_find_ind(ht, str); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - value = NULL; - break; - } - } - - if (opline->extended_value & ZEND_ISSET) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); - } - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { - result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check element of non-array"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ - zval tmp; - - result = 0; - if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(offset); - } - if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ - || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ - && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { - ZVAL_DUP(&tmp, offset); - convert_to_long(&tmp); - offset = &tmp; - } - } - if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { - if ((opline->extended_value & ZEND_ISSET) || - Z_STRVAL_P(container)[offset->value.lval] != '0') { - result = 1; - } - } - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); - } - - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *container; - int result; - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - - if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); - } - - zval_ptr_dtor_nogc(free_op2); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *expr; - zend_bool result; - - SAVE_OPLINE(); - expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; - - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); - } else { - result = 0; - } - ZVAL_BOOL(EX_VAR(opline->result.var), result); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -40196,21 +34204,21 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG } /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { + if (IS_UNUSED == IS_CONST) { ZVAL_DUP(&generator->key, key); - } else if (IS_VAR == IS_TMP_VAR) { + } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { + } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); + } else { ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { + if (IS_UNUSED == IS_CV) { if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); } } @@ -40246,32 +34254,292 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_POW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper_SPEC_CV_UNUSED(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + SAVE_OPLINE(); - pow_function(EX_VAR(opline->result.var), + fast_add_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + fast_sub_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + fast_mul_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + fast_div_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + fast_mod_function(EX_VAR(opline->result.var), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_binary_assign_op_helper_SPEC_CV_VAR(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + USE_OPLINE + + + SAVE_OPLINE(); + shift_left_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + shift_right_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + concat_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + fast_is_identical_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_is_not_identical_function(result, + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_not_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_is_smaller_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_is_smaller_or_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + bitwise_or_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + bitwise_and_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + bitwise_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + + SAVE_OPLINE(); + boolean_xor_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op_data1; zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - zval *property = NULL; + zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *value; zval *zptr; @@ -40297,7 +34565,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); SEPARATE_ZVAL_NOREF(zptr); @@ -40312,7 +34580,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b if (opline->extended_value == ZEND_ASSIGN_OBJ) { if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); } } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { if (Z_OBJ_HT_P(object)->read_dimension) { @@ -40333,7 +34601,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b SEPARATE_ZVAL_IF_NOT_REF(z); binary_op(z, z, value TSRMLS_CC); if (opline->extended_value == ZEND_ASSIGN_OBJ) { - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } @@ -40358,7 +34626,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op_data1; @@ -40377,11 +34645,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = NULL; + zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); var_ptr = Z_INDIRECT(rv); @@ -40413,7 +34681,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -40421,7 +34689,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar zval *value; SAVE_OPLINE(); - value = NULL; + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -40448,298 +34716,339 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_CV_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_CV_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_CV_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_CV_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_helper_SPEC_CV_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(opline->extended_value == 0)) { + return zend_binary_assign_op_helper_SPEC_CV_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { + return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { + return zend_binary_assign_op_obj_helper_SPEC_CV_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + +static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object; + zval *property; + zval *retval; + zval *zptr; + + SAVE_OPLINE(); + object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + retval = EX_VAR(opline->result.var); + + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(retval); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + /* here we are sure we are dealing with an object */ + + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { + zval rv; + + if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); + } + ZVAL_COPY_VALUE(z, value); + } + if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + SEPARATE_ZVAL_IF_NOT_REF(z); + incdec_op(z); + ZVAL_COPY_VALUE(retval, z); + Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + SELECTIVE_PZVAL_LOCK(retval, opline); + zval_ptr_dtor(z); + } else { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(retval); + } + } } -} -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + return zend_pre_incdec_property_helper_SPEC_CV_CV(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + return zend_pre_incdec_property_helper_SPEC_CV_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + zval *object; + zval *property; + zval *retval; + zval *zptr; -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); + object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + retval = EX_VAR(opline->result.var); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ } -} -static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *varname; - zval *retval; - zend_string *name; - HashTable *target_symbol_table; + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ZVAL_NULL(retval); - if (IS_CV == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - zend_string_addref(name); - } else { - name = zval_get_string(varname); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; + /* here we are sure we are dealing with an object */ - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - if (IS_CV != IS_CONST) { - zend_string_release(name); - } + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + ZVAL_DEREF(zptr); + ZVAL_COPY_VALUE(retval, zptr); + zval_opt_copy_ctor(zptr); + incdec_op(zptr); } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - retval = zend_hash_find(target_symbol_table, name); - if (retval == NULL) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - switch (type) { - case BP_VAR_R: - case BP_VAR_UNSET: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", name->val); - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); - break; - EMPTY_SWITCH_DEFAULT_CASE() + if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { + zval rv; + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval z_copy; + + if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { + zval rv; + zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + + if (Z_REFCOUNT_P(z) == 0) { + zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); } + ZVAL_COPY_VALUE(z, value); } - } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1 TSRMLS_CC); - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - + ZVAL_DUP(retval, z); + ZVAL_DUP(&z_copy, z); + incdec_op(&z_copy); + if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); + Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + zval_ptr_dtor(&z_copy); + zval_ptr_dtor(z); + } else { + zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); + ZVAL_NULL(retval); } } - if (IS_CV != IS_CONST) { - zend_string_release(name); - } - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { - ZVAL_UNREF(retval); - } - ZVAL_COPY(EX_VAR(opline->result.var), retval); - } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_post_incdec_property_helper_SPEC_CV_CV(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_post_incdec_property_helper_SPEC_CV_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} + zval *container; -static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); -static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -40752,7 +35061,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -40762,7 +35071,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -40775,7 +35084,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_H zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } ZVAL_DEREF(container); - zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -40785,7 +35094,22 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_H ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -40802,18 +35126,18 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } } else { - if (IS_UNUSED == IS_UNUSED) { + if (IS_CV == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); } @@ -40821,1073 +35145,1200 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *object_ptr; + zend_free_op free_op1; + zval *container; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - ZVAL_DEREF(object_ptr); - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - - zval *property_name = NULL; - - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - - } else { - zend_free_op free_op_data1; - zval rv; - zval *value; - zval *dim = NULL; - zval *variable_ptr; - - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && - EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - FREE_OP(free_op_data1); - } else { - zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_UNUSED TSRMLS_CC); + ZVAL_DEREF(container); + zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - variable_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); - if ((opline+1)->op1_type == IS_VAR) { - FREE_OP(free_op_data1); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - } - } + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - /* assign_dim has two opcodes! */ CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; + zval *container; + + zval *offset; SAVE_OPLINE(); - if ((IS_CV == IS_VAR || IS_CV == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); - } - ZVAL_MAKE_REF(expr_ptr); - Z_ADDREF_P(expr_ptr); + container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + ZVAL_NULL(EX_VAR(opline->result.var)); } else { - expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } else if (IS_CV == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); - expr_ptr = &new_expr; - } - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(expr_ptr)) { - expr_ptr = Z_REFVAL_P(expr_ptr); - if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); - - } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } - } - - if (IS_UNUSED != IS_UNUSED) { + zval *retval; - zval *offset = NULL; - zend_string *str; - zend_ulong hval; + /* here we are sure we are dealing with an object */ + do { + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); -add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_UNUSED != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; - } - - } else { - zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zval *array; - uint32_t size; - USE_OPLINE - - array = EX_VAR(opline->result.var); - if (IS_CV != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_NEW_ARR(array); - zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); - - if (IS_CV != IS_UNUSED) { - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init(Z_ARRVAL_P(array), 0); - } - } - - if (IS_CV == IS_UNUSED) { - ZEND_VM_NEXT_OPCODE(); -#if 0 || IS_CV != IS_UNUSED - } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#endif - } -} - -static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval tmp, *varname; - HashTable *target_symbol_table; - - - SAVE_OPLINE(); - if (IS_CV == IS_CV && - IS_UNUSED == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - zval *var = EX_VAR(opline->op1.var); - - if (Z_REFCOUNTED_P(var)) { - zend_refcounted *garbage = Z_COUNTED_P(var); - - if (!--GC_REFCOUNT(garbage)) { - ZVAL_UNDEF(var); - _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); - } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); - } - } else { - ZVAL_UNDEF(var); - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - ZVAL_UNDEF(&tmp); - if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; } - - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); - } - if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } while (0); } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; + zend_free_op free_op1; + zval *property; + zval *container; SAVE_OPLINE(); - if (IS_CV == IS_CV && - IS_UNUSED == IS_UNUSED && - (opline->extended_value & ZEND_QUICK_SET)) { - value = EX_VAR(opline->op1.var); - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !i_zend_is_true(value TSRMLS_CC)); - CHECK_EXCEPTION(); - } - ZEND_VM_NEXT_OPCODE(); - } else { - - zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - - ZVAL_UNDEF(&tmp); - if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_STR(&tmp, zval_get_string(varname)); - varname = &tmp; - } - - if (IS_UNUSED != IS_UNUSED) { - zend_class_entry *ce; - - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); - if (UNEXPECTED(ce == NULL)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - } else { - HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); - } + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { - zend_string_release(Z_STR(tmp)); - } + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } - if (opline->extended_value & ZEND_ISSET) { - ZVAL_BOOL(EX_VAR(opline->result.var), - value && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - ZVAL_BOOL(EX_VAR(opline->result.var), - !value || !i_zend_is_true(value TSRMLS_CC)); - } + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op1; + zval *property; + zval *container; - /* The generator object is stored in EX(return_value) */ - zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } - /* Set the new yielded value */ - if (IS_CV != IS_UNUSED) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zval *value; + zval *container; - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + zval *offset; - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + SAVE_OPLINE(); + container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - /* Temporary variables don't need ctor copying */ - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); - } - } else { - zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; - if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); - } + /* here we are sure we are dealing with an object */ + do { + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { + zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); + zend_object *zobj = Z_OBJ_P(container); - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - } else { - ZVAL_MAKE_REF(value_ptr); + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); + if (EXPECTED(retval)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + break; + } } - ZVAL_COPY(&generator->value, value_ptr); - } - } else { - zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->value, value); - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); + } while (0); } - /* Set the new yielded key */ - if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->key, key); - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + /* Behave like FETCH_OBJ_W */ + zend_free_op free_op1; + zval *property; + + SAVE_OPLINE(); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } else { - generator->send_target = NULL; + return ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); } -static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_binary_assign_op_helper_SPEC_CV_UNUSED(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op1; + zval *container, *property; SAVE_OPLINE(); - fast_add_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *object; + zval *property_name; SAVE_OPLINE(); - fast_sub_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + + /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *object_ptr; SAVE_OPLINE(); - fast_mul_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); -static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + } else { + zend_free_op free_op_data1; + zval rv; + zval *value; + zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + zval *variable_ptr; - SAVE_OPLINE(); - fast_div_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); + } else { + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CV TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + FREE_OP(free_op_data1); + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } + } + /* assign_dim has two opcodes! */ CHECK_EXCEPTION(); + ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *value; + zval *variable_ptr; SAVE_OPLINE(); - fast_mod_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_CV == IS_TMP_VAR) { + + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + } + /* zend_assign_to_variable() always takes care of op2, never free it! */ CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *variable_ptr; + zval *value_ptr; SAVE_OPLINE(); - shift_left_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + if (!0) { + PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ + } + zend_error(E_STRICT, "Only variables should be assigned by reference"); + if (UNEXPECTED(EG(exception) != NULL)) { + + HANDLE_EXCEPTION(); + } + return ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { + if (!0) { + PZVAL_LOCK(value_ptr); + } + } + + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } + if (IS_CV == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(variable_ptr))) { + zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); + } + if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || + (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { + variable_ptr = &EG(uninitialized_zval); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr TSRMLS_CC); + } + + if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { + if (!0) { + Z_DELREF_P(variable_ptr); + } + } + + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; SAVE_OPLINE(); - shift_right_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (IS_CV != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Method name must be a string"); + } + + object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + + if (UNEXPECTED(EG(exception) != NULL)) { + + HANDLE_EXCEPTION(); + } + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); -static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); + } - SAVE_OPLINE(); - concat_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + obj = Z_OBJ_P(object); + called_scope = obj->ce; + if (IS_CV != IS_CONST || + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { + zend_object *orig_obj = obj; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (UNEXPECTED(obj->handlers->get_method == NULL)) { + zend_error_noreturn(E_ERROR, "Object does not support method calls"); + } -static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + } + if (IS_CV == IS_CONST && + EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc); + } + } + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + obj = NULL; + } else { + GC_REFCOUNT(obj)++; /* For $this pointer */ + } - SAVE_OPLINE(); - fast_is_identical_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - fast_is_not_identical_function(result, - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - + fast_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *result = EX_VAR(opline->result.var); + zval *expr_ptr, new_expr; SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && + (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + } + ZVAL_MAKE_REF(expr_ptr); + Z_ADDREF_P(expr_ptr); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + } else { + expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } else if (IS_CV == IS_CONST) { + if (!Z_IMMUTABLE_P(expr_ptr)) { + ZVAL_DUP(&new_expr, expr_ptr); + expr_ptr = &new_expr; + } + } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(expr_ptr)) { + expr_ptr = Z_REFVAL_P(expr_ptr); + if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr); -static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } - zval *result = EX_VAR(opline->result.var); + if (IS_CV != IS_UNUSED) { - SAVE_OPLINE(); - fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + zend_string *str; + zend_ulong hval; +add_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index; + case IS_FALSE: + hval = 0; + goto num_index; + case IS_TRUE: + hval = 1; + goto num_index; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto add_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); + /* do nothing */ + break; + } + } else { + zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zval *array; + uint32_t size; USE_OPLINE - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + array = EX_VAR(opline->result.var); + if (IS_CV != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + } else { + size = 0; + } + ZVAL_NEW_ARR(array); + zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0); + if (IS_CV != IS_UNUSED) { + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init(Z_ARRVAL_P(array), 0); + } + } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (IS_CV == IS_UNUSED) { + ZEND_VM_NEXT_OPCODE(); +#if 0 || IS_CV != IS_UNUSED + } else { + return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +#endif + } } -static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *result = EX_VAR(opline->result.var); + zval *container; + zval *offset; + zend_ulong hval; SAVE_OPLINE(); - fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + SEPARATE_ZVAL_NOREF(container); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); +offset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; + } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } + + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_CV == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *container; + zval *offset; SAVE_OPLINE(); - bitwise_or_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->unset_property) { + Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to unset property of non-object"); + } + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *container; + int result; + zend_ulong hval; + zval *offset; SAVE_OPLINE(); - bitwise_and_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - + container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value; + zend_string *str; -static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } +str_index_prop: + value = zend_hash_find_ind(ht, str); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else { + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 1; + goto num_index_prop; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto isset_again; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + value = NULL; + break; + } + } + if (opline->extended_value & ZEND_ISSET) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check element of non-array"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ + zval tmp; - SAVE_OPLINE(); - bitwise_xor_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(offset); + } + if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ + || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */ + && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) { + ZVAL_DUP(&tmp, offset); + convert_to_long(&tmp); + offset = &tmp; + } + } + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { + if ((opline->extended_value & ZEND_ISSET) || + Z_STRVAL_P(container)[offset->value.lval] != '0') { + result = 1; + } + } + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *container; + int result; + zval *offset; SAVE_OPLINE(); - boolean_xor_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data1; - zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zval *value; - zval *zptr; - if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); - } + /* The generator object is stored in EX(return_value) */ + zend_generator *generator = (zend_generator *) EX(return_value); - if (IS_CV != IS_UNUSED) { - object = make_real_object(object TSRMLS_CC); + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); } - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - zend_error(E_WARNING, "Attempt to assign property of non-object"); + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - FREE_OP(free_op_data1); + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - /* here we are sure we are dealing with an object */ - if (opline->extended_value == ZEND_ASSIGN_OBJ - && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } else { - zval *z = NULL; - zval rv; + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); - } - } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv TSRMLS_CC); - } - } - if (z) { - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { - zval rv; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - if (Z_REFCOUNT_P(z) == 0) { - zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC); - } - ZVAL_COPY_VALUE(z, value); + /* Temporary variables don't need ctor copying */ + if (IS_CV != IS_TMP_VAR) { + zval_opt_copy_ctor(&generator->value); } -//??? if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - SEPARATE_ZVAL_IF_NOT_REF(z); - binary_op(z, z, value TSRMLS_CC); - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); + } else { + zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), z); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + } else { + ZVAL_MAKE_REF(value_ptr); } - zval_ptr_dtor(z); + ZVAL_COPY(&generator->value, value_ptr); + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST) { + ZVAL_DUP(&generator->value, value); + } else if (IS_CV == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { + ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); } } } - - FREE_OP(free_op_data1); + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } - /* assign_obj has two opcodes! */ - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op_data1; - zval *var_ptr, rv; - zval *value, *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } + /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_CV == IS_VAR && !0) { - Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ - } - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - } + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST) { + ZVAL_DUP(&generator->key, key); + } else if (IS_CV == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->key, key); + } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) { + ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + ZVAL_COPY_VALUE(&generator->key, key); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + } } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - binary_op(var_ptr, var_ptr, value TSRMLS_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); } - FREE_OP(free_op_data1); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } - CHECK_EXCEPTION(); + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); } -static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } - - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - binary_op(var_ptr, var_ptr, value TSRMLS_CC); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - } + pow_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + return zend_binary_assign_op_helper_SPEC_CV_CV(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op2; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); + fast_add_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op2; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } -} - -static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); + fast_sub_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op2; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + SAVE_OPLINE(); + fast_mul_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op2; - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + SAVE_OPLINE(); + fast_div_function(EX_VAR(opline->result.var), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op2; + zval *result = EX_VAR(opline->result.var); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + SAVE_OPLINE(); + fast_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op2; + zval *result = EX_VAR(opline->result.var); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + SAVE_OPLINE(); + fast_not_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op2; + zval *result = EX_VAR(opline->result.var); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + SAVE_OPLINE(); + fast_is_smaller_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op2; + zval *result = EX_VAR(opline->result.var); - if (EXPECTED(opline->extended_value == 0)) { - return zend_binary_assign_op_helper_SPEC_CV_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - return zend_binary_assign_op_obj_helper_SPEC_CV_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } + SAVE_OPLINE(); + fast_is_smaller_or_equal_function(result, + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op2; zval *object; zval *property; zval *retval; @@ -41895,7 +36346,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); retval = EX_VAR(opline->result.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { @@ -41908,7 +36359,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - + zval_ptr_dtor_nogc(free_op2); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(retval); } @@ -41920,7 +36371,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc /* here we are sure we are dealing with an object */ if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); SEPARATE_ZVAL_NOREF(zptr); @@ -41933,7 +36384,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { zval rv; @@ -41948,7 +36399,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc SEPARATE_ZVAL_IF_NOT_REF(z); incdec_op(z); ZVAL_COPY_VALUE(retval, z); - Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); SELECTIVE_PZVAL_LOCK(retval, opline); zval_ptr_dtor(z); } else { @@ -41959,25 +36410,26 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc } } + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_pre_incdec_property_helper_SPEC_CV_CV(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_pre_incdec_property_helper_SPEC_CV_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op2; zval *object; zval *property; zval *retval; @@ -41985,7 +36437,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); retval = EX_VAR(opline->result.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { @@ -41998,7 +36450,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - + zval_ptr_dtor_nogc(free_op2); ZVAL_NULL(retval); CHECK_EXCEPTION(); @@ -42008,7 +36460,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in /* here we are sure we are dealing with an object */ if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) - && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { ZVAL_DEREF(zptr); ZVAL_COPY_VALUE(retval, zptr); @@ -42018,7 +36470,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); + zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); zval z_copy; if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { @@ -42034,7 +36486,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in ZVAL_DUP(&z_copy, z); incdec_op(&z_copy); if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z); - Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); zval_ptr_dtor(&z_copy); zval_ptr_dtor(z); } else { @@ -42043,167 +36495,33 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in } } + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_post_incdec_property_helper_SPEC_CV_CV(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_post_incdec_property_helper_SPEC_CV_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - zval *container; - zend_free_op free_op1; - - SAVE_OPLINE(); - - if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } - container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - - - } else { - if (IS_CV == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - - - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + return zend_post_incdec_property_helper_SPEC_CV_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - zend_free_op free_op1; - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(container); - zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - - if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + return zend_post_incdec_property_helper_SPEC_CV_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; - + zend_free_op free_op2; zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -42214,7 +36532,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE /* here we are sure we are dealing with an object */ do { - if (IS_CV == IS_CONST && + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); zend_object *zobj = Z_OBJ_P(container); @@ -42234,7 +36552,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE } } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); if (retval != EX_VAR(opline->result.var)) { ZVAL_COPY(EX_VAR(opline->result.var), retval); @@ -42242,28 +36560,29 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE } while (0); } + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval *property; zval *container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -42272,22 +36591,22 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval *property; zval *container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); - + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -42296,17 +36615,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; - + zend_free_op free_op2; zval *offset; SAVE_OPLINE(); container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -42316,7 +36635,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL /* here we are sure we are dealing with an object */ do { - if (IS_CV == IS_CONST && + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1); zend_object *zobj = Z_OBJ_P(container); @@ -42336,7 +36655,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL } } - retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC); if (retval != EX_VAR(opline->result.var)) { ZVAL_COPY(EX_VAR(opline->result.var), retval); @@ -42344,23 +36663,24 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL } while (0); } + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval *property; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { @@ -42369,8 +36689,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); - + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -42378,25 +36698,25 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval *container, *property; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); - + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -42405,22 +36725,22 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op2; zval *object; zval *property_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); @@ -42428,168 +36748,11 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *object_ptr; - - SAVE_OPLINE(); - object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } - ZVAL_DEREF(object_ptr); - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - - zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - - } else { - zend_free_op free_op_data1; - zval rv; - zval *value; - zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zval *variable_ptr; - - if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && - EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - FREE_OP(free_op_data1); - } else { - zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CV TSRMLS_CC); - - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - variable_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); - if ((opline+1)->op1_type == IS_VAR) { - FREE_OP(free_op_data1); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - } - } - } - - /* assign_dim has two opcodes! */ - CHECK_EXCEPTION(); - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_CV == IS_TMP_VAR) { - - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CV TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *variable_ptr; - zval *value_ptr; - - SAVE_OPLINE(); - value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } - if (IS_CV == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!0) { - PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ - } - zend_error(E_STRICT, "Only variables should be assigned by reference"); - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - return ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { - if (!0) { - PZVAL_LOCK(value_ptr); - } - } - - variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } - if (IS_CV == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); - } - if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || - (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { - variable_ptr = &EG(uninitialized_zval); - } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr TSRMLS_CC); - } - - if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) { - if (!0) { - Z_DELREF_P(variable_ptr); - } - } - - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); - } - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; - + zend_free_op free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -42597,9 +36760,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); - function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (IS_CV != IS_CONST && + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -42613,12 +36776,12 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H uint32_t nesting = 1; if (UNEXPECTED(EG(exception) != NULL)) { - + zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); } zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - + zval_ptr_dtor_nogc(free_op2); if (EG(exception) != NULL) { HANDLE_EXCEPTION(); @@ -42656,7 +36819,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H obj = Z_OBJ_P(object); called_scope = obj->ce; - if (IS_CV != IS_CONST || + if ((IS_TMP_VAR|IS_VAR) != IS_CONST || EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; @@ -42665,11 +36828,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H } /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } - if (IS_CV == IS_CONST && + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && EXPECTED(obj == orig_obj)) { @@ -42686,27 +36849,29 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op2; zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); fast_equal_function(result, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -42741,9 +36906,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ } } - if (IS_CV != IS_UNUSED) { - - zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zend_free_op free_op2; + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); zend_string *str; zend_ulong hval; @@ -42759,7 +36924,7 @@ num_index: break; case IS_STRING: str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index; } @@ -42786,7 +36951,7 @@ str_index: /* do nothing */ break; } - + zval_ptr_dtor_nogc(free_op2); } else { zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } @@ -42794,7 +36959,7 @@ str_index: ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -42820,15 +36985,15 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_NEXT_OPCODE(); #if 0 || IS_CV != IS_UNUSED } else { - return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #endif } } -static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op2; zval *container; zval *offset; zend_ulong hval; @@ -42842,7 +37007,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_DEREF(container); } SEPARATE_ZVAL_NOREF(container); - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); @@ -42858,7 +37023,7 @@ num_index_dim: zend_hash_index_del(ht, hval); break; case IS_STRING: - if (IS_CV != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { goto num_index_dim; } @@ -42889,31 +37054,31 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - + zval_ptr_dtor_nogc(free_op2); } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use object as array"); } -//??? if (IS_CV == IS_CONST) { +//??? if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { //??? zval_copy_ctor(offset); //??? } Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - + zval_ptr_dtor_nogc(free_op2); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ } else { - + zval_ptr_dtor_nogc(free_op2); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op2; zval *container; zval *offset; @@ -42922,28 +37087,28 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_CV != IS_UNUSED) { ZVAL_DEREF(container); } if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to unset property of non-object"); } } - + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - + zend_free_op free_op2; zval *container; int result; zend_ulong hval; @@ -42951,7 +37116,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPC SAVE_OPLINE(); container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); @@ -42961,7 +37126,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPC isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index_prop; } @@ -43021,7 +37186,7 @@ num_index_prop: result = 0; if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { - if (IS_CV == IS_CV || IS_CV == IS_VAR) { + if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) { ZVAL_DEREF(offset); } if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */ @@ -43047,451 +37212,1219 @@ num_index_prop: result = ((opline->extended_value & ZEND_ISSET) == 0); } + zval_ptr_dtor_nogc(free_op2); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *container; + int result; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + zval_ptr_dtor_nogc(free_op2); ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *retval = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ + ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1) TSRMLS_CC)); + zval_ptr_dtor_nogc(free_op1); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_op_array *new_op_array=NULL; + zend_free_op free_op1; + zval *inc_filename; + zval tmp_inc_filename; + zend_bool failure_retval=0; + + SAVE_OPLINE(); + inc_filename = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + + ZVAL_UNDEF(&tmp_inc_filename); + if (Z_TYPE_P(inc_filename) != IS_STRING) { + ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); + inc_filename = &tmp_inc_filename; + } + + if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) { + if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) { + zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + } else { + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + } + } else { + switch (opline->extended_value) { + case ZEND_INCLUDE_ONCE: + case ZEND_REQUIRE_ONCE: { + zend_file_handle file_handle; + char *resolved_path; + + resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename) TSRMLS_CC); + if (resolved_path) { + failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path)); + } else { + resolved_path = Z_STRVAL_P(inc_filename); + } + + if (failure_retval) { + /* do nothing, file already included */ + } else if (SUCCESS == zend_stream_open(resolved_path, &file_handle TSRMLS_CC)) { + + if (!file_handle.opened_path) { + file_handle.opened_path = estrdup(resolved_path); + } + + if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) { + new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC); + zend_destroy_file_handle(&file_handle TSRMLS_CC); + } else { + zend_file_handle_dtor(&file_handle TSRMLS_CC); + failure_retval=1; + } + } else { + if (opline->extended_value == ZEND_INCLUDE_ONCE) { + zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + } else { + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC); + } + } + if (resolved_path != Z_STRVAL_P(inc_filename)) { + efree(resolved_path); + } + } + break; + case ZEND_INCLUDE: + case ZEND_REQUIRE: + new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC); + break; + case ZEND_EVAL: { + char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); + + new_op_array = zend_compile_string(inc_filename, eval_desc TSRMLS_CC); + efree(eval_desc); + } + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } + if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) { + zend_string_release(Z_STR(tmp_inc_filename)); + } + zval_ptr_dtor_nogc(free_op1); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } else if (EXPECTED(new_op_array != NULL)) { + zval *return_value = NULL; + zend_execute_data *call; + + if (RETURN_VALUE_USED(opline)) { + return_value = EX_VAR(opline->result.var); + } + + new_op_array->scope = EG(scope); /* ??? */ + + call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, + (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL TSRMLS_CC); + + if (EX(symbol_table)) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); + } + + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value TSRMLS_CC); + if (EXPECTED(zend_execute_ex == execute_ex)) { + ZEND_VM_ENTER(); + } else { + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call TSRMLS_CC); + } + + destroy_op_array(new_op_array TSRMLS_CC); + efree_size(new_op_array, sizeof(zend_op_array)); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + HANDLE_EXCEPTION(); + } + + } else if (RETURN_VALUE_USED(opline)) { + ZVAL_BOOL(EX_VAR(opline->result.var), failure_retval); + } + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_ADD_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + + SAVE_OPLINE(); + fast_add_function(EX_VAR(opline->result.var), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + opline->op2.zv TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_SUB_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + + SAVE_OPLINE(); + fast_sub_function(EX_VAR(opline->result.var), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + opline->op2.zv TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_MUL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + + SAVE_OPLINE(); + fast_mul_function(EX_VAR(opline->result.var), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + opline->op2.zv TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + + SAVE_OPLINE(); + fast_div_function(EX_VAR(opline->result.var), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + opline->op2.zv TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_equal_function(result, + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + opline->op2.zv TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *container; - int result; - zval *offset; + zend_free_op free_op1; + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - - if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { - result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); - } else { - zend_error(E_NOTICE, "Trying to check property of non-object"); - result = 0; - } - if ((opline->extended_value & ZEND_ISSET) == 0) { - result = !result; - } - } else { - result = ((opline->extended_value & ZEND_ISSET) == 0); - } - - ZVAL_BOOL(EX_VAR(opline->result.var), result); + fast_not_equal_function(result, + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + opline->op2.zv TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zend_free_op free_op1; + zval *result = EX_VAR(opline->result.var); - /* The generator object is stored in EX(return_value) */ - zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); + fast_is_smaller_function(result, + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + opline->op2.zv TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); - } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); +static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *result = EX_VAR(opline->result.var); - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); + SAVE_OPLINE(); + fast_is_smaller_or_equal_function(result, + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + opline->op2.zv TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); - /* Set the new yielded value */ - if (IS_CV != IS_UNUSED) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} +static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(int type, ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *varname; + zval *retval; + zend_string *name; + HashTable *target_symbol_table; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zval *value; + SAVE_OPLINE(); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + zend_string_addref(name); + } else { + name = zval_get_string(varname); + } - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (IS_CONST != IS_UNUSED) { + zend_class_entry *ce; - /* Temporary variables don't need ctor copying */ - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); - } + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else { - zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - - if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); - } - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - } else { - ZVAL_MAKE_REF(value_ptr); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(name); + } + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } - ZVAL_COPY(&generator->value, value_ptr); - + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); } } else { - zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->value, value); - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + retval = zend_std_get_static_property(ce, name, 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + retval = zend_hash_find(target_symbol_table, name); + if (retval == NULL) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() } } } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_CV != IS_UNUSED) { - - zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->key, key); - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { + if (Z_CONSTANT_P(retval)) { + zval_update_constant(retval, 1 TSRMLS_CC); } + } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + zval_ptr_dtor_nogc(free_op1); } + } - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(name); } - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - generator->send_target = NULL; + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); +static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); +static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - ZEND_VM_RETURN(); +static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - SAVE_OPLINE(); - pow_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); +static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_binary_assign_op_helper_SPEC_CV_CV(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zend_free_op free_op1; + zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - fast_add_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + fast_equal_function(result, + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval tmp, *varname; + HashTable *target_symbol_table; + zend_free_op free_op1; SAVE_OPLINE(); - fast_sub_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && + IS_CONST == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + zval *var = EX_VAR(opline->op1.var); - zval_ptr_dtor_nogc(free_op2); + if (Z_REFCOUNTED_P(var)) { + zend_refcounted *garbage = Z_COUNTED_P(var); + + if (!--GC_REFCOUNT(garbage)) { + ZVAL_UNDEF(var); + _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); + } else { + GC_ZVAL_CHECK_POSSIBLE_ROOT(var); + ZVAL_UNDEF(var); + } + } else { + ZVAL_UNDEF(var); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + + ZVAL_UNDEF(&tmp); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } + + if (IS_CONST != IS_UNUSED) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + zend_std_unset_static_property(ce, Z_STR_P(varname), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; + zval *value; SAVE_OPLINE(); - fast_mul_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && + IS_CONST == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); + } else { + zend_free_op free_op1; + zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zval_ptr_dtor_nogc(free_op2); + ZVAL_UNDEF(&tmp); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } + + if (IS_CONST != IS_UNUSED) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + zval_ptr_dtor_nogc(free_op1); + + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } +} + +static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(int type, ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *varname; + zval *retval; + zend_string *name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + zend_string_addref(name); + } else { + name = zval_get_string(varname); + } + + if (IS_VAR != IS_UNUSED) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(name); + } + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + retval = zend_std_get_static_property(ce, name, 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + retval = zend_hash_find(target_symbol_table, name); + if (retval == NULL) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } + } + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { + if (Z_CONSTANT_P(retval)) { + zval_update_constant(retval, 1 TSRMLS_CC); + } + } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + zval_ptr_dtor_nogc(free_op1); + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(name); + } + + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - zend_free_op free_op2; + return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - SAVE_OPLINE(); - fast_div_function(EX_VAR(opline->result.var), - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); +static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); +static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } -static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - zend_free_op free_op2; - zval *result = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); +static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; - zval *result = EX_VAR(opline->result.var); + zval tmp, *varname; + HashTable *target_symbol_table; + zend_free_op free_op1; SAVE_OPLINE(); - fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && + IS_VAR == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + zval *var = EX_VAR(opline->op1.var); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if (Z_REFCOUNTED_P(var)) { + zend_refcounted *garbage = Z_COUNTED_P(var); -static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *result = EX_VAR(opline->result.var); + if (!--GC_REFCOUNT(garbage)) { + ZVAL_UNDEF(var); + _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); + } else { + GC_ZVAL_CHECK_POSSIBLE_ROOT(var); + ZVAL_UNDEF(var); + } + } else { + ZVAL_UNDEF(var); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } - SAVE_OPLINE(); - fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + ZVAL_UNDEF(&tmp); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } -static int ZEND_FASTCALL ZEND_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (IS_VAR != IS_UNUSED) { + zend_class_entry *ce; - SAVE_OPLINE(); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + zend_std_unset_static_property(ce, Z_STR_P(varname), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_ADD_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; + zval *value; SAVE_OPLINE(); - fast_add_function(EX_VAR(opline->result.var), - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && + IS_VAR == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); + } else { + zend_free_op free_op1; + zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + ZVAL_UNDEF(&tmp); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } -static int ZEND_FASTCALL ZEND_SUB_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; + if (IS_VAR != IS_UNUSED) { + zend_class_entry *ce; - SAVE_OPLINE(); - fast_sub_function(EX_VAR(opline->result.var), - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); + } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + zval_ptr_dtor_nogc(free_op1); + + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } -static int ZEND_FASTCALL ZEND_MUL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; + zval *varname; + zval *retval; + zend_string *name; + HashTable *target_symbol_table; SAVE_OPLINE(); - fast_mul_function(EX_VAR(opline->result.var), - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + zend_string_addref(name); + } else { + name = zval_get_string(varname); + } -static int ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; + if (IS_UNUSED != IS_UNUSED) { + zend_class_entry *ce; - SAVE_OPLINE(); - fast_div_function(EX_VAR(opline->result.var), - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + if (IS_UNUSED == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(name); + } + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + retval = zend_std_get_static_property(ce, name, 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op1); + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + retval = zend_hash_find(target_symbol_table, name); + if (retval == NULL) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", name->val); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } + } + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { + if (Z_CONSTANT_P(retval)) { + zval_update_constant(retval, 1 TSRMLS_CC); + } + } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + zval_ptr_dtor_nogc(free_op1); + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(name); + } + + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - zend_free_op free_op1; - zval *result = EX_VAR(opline->result.var); + return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - SAVE_OPLINE(); - fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); +static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); +static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *result = EX_VAR(opline->result.var); - SAVE_OPLINE(); - fast_not_equal_function(result, - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); +static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval tmp, *varname; + HashTable *target_symbol_table; zend_free_op free_op1; - zval *result = EX_VAR(opline->result.var); SAVE_OPLINE(); - fast_is_smaller_function(result, - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && + IS_UNUSED == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + zval *var = EX_VAR(opline->op1.var); + + if (Z_REFCOUNTED_P(var)) { + zend_refcounted *garbage = Z_COUNTED_P(var); + + if (!--GC_REFCOUNT(garbage)) { + ZVAL_UNDEF(var); + _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); + } else { + GC_ZVAL_CHECK_POSSIBLE_ROOT(var); + ZVAL_UNDEF(var); + } + } else { + ZVAL_UNDEF(var); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + + ZVAL_UNDEF(&tmp); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } + if (IS_UNUSED != IS_UNUSED) { + zend_class_entry *ce; + + if (IS_UNUSED == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv)); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + zend_std_unset_static_property(ce, Z_STR_P(varname), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *result = EX_VAR(opline->result.var); + zval *value; SAVE_OPLINE(); - fast_is_smaller_or_equal_function(result, - _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), - opline->op2.zv TSRMLS_CC); - zval_ptr_dtor_nogc(free_op1); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && + IS_UNUSED == IS_UNUSED && + (opline->extended_value & ZEND_QUICK_SET)) { + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); + } else { + zend_free_op free_op1; + zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + ZVAL_UNDEF(&tmp); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; + } + + if (IS_UNUSED != IS_UNUSED) { + zend_class_entry *ce; + + if (IS_UNUSED == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); + } else { + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } + zval_ptr_dtor_nogc(free_op1); + + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_ADD_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -43618,6 +38551,21 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CV_HANDLER(ZEND_O ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_equal_function(result, + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -43742,6 +38690,22 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZE ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + fast_equal_function(result, + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2) TSRMLS_CC); + + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type); @@ -44953,28 +39917,28 @@ void zend_init_opcodes_handlers(void) ZEND_JMPNZ_EX_SPEC_CV_HANDLER, ZEND_JMPNZ_EX_SPEC_CV_HANDLER, ZEND_CASE_SPEC_CONST_CONST_HANDLER, - ZEND_CASE_SPEC_CONST_TMP_HANDLER, - ZEND_CASE_SPEC_CONST_VAR_HANDLER, + ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER, + ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_CASE_SPEC_CONST_CV_HANDLER, - ZEND_CASE_SPEC_TMP_CONST_HANDLER, - ZEND_CASE_SPEC_TMP_TMP_HANDLER, - ZEND_CASE_SPEC_TMP_VAR_HANDLER, + ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER, + ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_CASE_SPEC_TMP_CV_HANDLER, - ZEND_CASE_SPEC_VAR_CONST_HANDLER, - ZEND_CASE_SPEC_VAR_TMP_HANDLER, - ZEND_CASE_SPEC_VAR_VAR_HANDLER, + ZEND_CASE_SPEC_TMPVAR_CV_HANDLER, + ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER, + ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_CASE_SPEC_VAR_CV_HANDLER, + ZEND_CASE_SPEC_TMPVAR_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_CASE_SPEC_CV_CONST_HANDLER, - ZEND_CASE_SPEC_CV_TMP_HANDLER, - ZEND_CASE_SPEC_CV_VAR_HANDLER, + ZEND_CASE_SPEC_CV_TMPVAR_HANDLER, + ZEND_CASE_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_CASE_SPEC_CV_CV_HANDLER, ZEND_NULL_HANDLER, @@ -45057,16 +40021,16 @@ void zend_init_opcodes_handlers(void) ZEND_BOOL_SPEC_CONST_HANDLER, ZEND_BOOL_SPEC_CONST_HANDLER, ZEND_BOOL_SPEC_CONST_HANDLER, - ZEND_BOOL_SPEC_TMP_HANDLER, - ZEND_BOOL_SPEC_TMP_HANDLER, - ZEND_BOOL_SPEC_TMP_HANDLER, - ZEND_BOOL_SPEC_TMP_HANDLER, - ZEND_BOOL_SPEC_TMP_HANDLER, - ZEND_BOOL_SPEC_VAR_HANDLER, - ZEND_BOOL_SPEC_VAR_HANDLER, - ZEND_BOOL_SPEC_VAR_HANDLER, - ZEND_BOOL_SPEC_VAR_HANDLER, - ZEND_BOOL_SPEC_VAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -45158,8 +40122,8 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER, - ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER, + ZEND_ADD_VAR_SPEC_TMP_TMPVAR_HANDLER, + ZEND_ADD_VAR_SPEC_TMP_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER, ZEND_NULL_HANDLER, @@ -45168,8 +40132,8 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ADD_VAR_SPEC_UNUSED_TMP_HANDLER, - ZEND_ADD_VAR_SPEC_UNUSED_VAR_HANDLER, + ZEND_ADD_VAR_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ADD_VAR_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER, ZEND_NULL_HANDLER, @@ -45528,43 +40492,43 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER, - ZEND_INIT_ARRAY_SPEC_CONST_TMP_HANDLER, - ZEND_INIT_ARRAY_SPEC_CONST_VAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER, ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER, ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER, ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER, - ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER, - ZEND_INIT_ARRAY_SPEC_TMP_VAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER, ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER, ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER, ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER, - ZEND_INIT_ARRAY_SPEC_VAR_TMP_HANDLER, - ZEND_INIT_ARRAY_SPEC_VAR_VAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER, ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER, ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER, ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER, - ZEND_INIT_ARRAY_SPEC_UNUSED_TMP_HANDLER, - ZEND_INIT_ARRAY_SPEC_UNUSED_VAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER, ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER, ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER, - ZEND_INIT_ARRAY_SPEC_CV_TMP_HANDLER, - ZEND_INIT_ARRAY_SPEC_CV_VAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER, ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER, ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER, ZEND_NULL_HANDLER, @@ -45573,8 +40537,8 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER, ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, @@ -45582,16 +40546,16 @@ void zend_init_opcodes_handlers(void) ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -45607,15 +40571,15 @@ void zend_init_opcodes_handlers(void) ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER, ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER, + ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER, - ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER, + ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HANDLER, + ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER, + ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER, - ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER, + ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HANDLER, + ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -45638,18 +40602,18 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER, - ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER, - ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER, + ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER, + ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER, ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER, - ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER, - ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER, + ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER, ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER, - ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER, - ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER, + ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER, + ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER, ZEND_NULL_HANDLER, @@ -45663,18 +40627,18 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER, - ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER, + ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER, ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER, - ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER, + ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER, ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER, - ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER, + ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER, ZEND_FE_RESET_SPEC_CONST_HANDLER, @@ -45757,15 +40721,15 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_R_SPEC_CONST_VAR_HANDLER, ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_R_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_R_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_R_SPEC_TMP_VAR_HANDLER, - ZEND_FETCH_R_SPEC_TMP_UNUSED_HANDLER, + ZEND_FETCH_R_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_R_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_R_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_R_SPEC_VAR_VAR_HANDLER, - ZEND_FETCH_R_SPEC_VAR_UNUSED_HANDLER, + ZEND_FETCH_R_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -45803,28 +40767,28 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER, ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER, ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER, ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER, ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_UNUSED_VAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER, ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CV_TMP_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER, ZEND_FETCH_W_SPEC_CONST_CONST_HANDLER, @@ -45832,15 +40796,15 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_W_SPEC_CONST_VAR_HANDLER, ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_W_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_W_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_W_SPEC_TMP_VAR_HANDLER, - ZEND_FETCH_W_SPEC_TMP_UNUSED_HANDLER, + ZEND_FETCH_W_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_W_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_W_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_W_SPEC_VAR_VAR_HANDLER, - ZEND_FETCH_W_SPEC_VAR_UNUSED_HANDLER, + ZEND_FETCH_W_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -45888,18 +40852,18 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER, ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER, ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER, ZEND_FETCH_RW_SPEC_CONST_CONST_HANDLER, @@ -45907,15 +40871,15 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_RW_SPEC_CONST_VAR_HANDLER, ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_RW_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_RW_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_RW_SPEC_TMP_VAR_HANDLER, - ZEND_FETCH_RW_SPEC_TMP_UNUSED_HANDLER, + ZEND_FETCH_RW_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_RW_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_RW_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_RW_SPEC_VAR_VAR_HANDLER, - ZEND_FETCH_RW_SPEC_VAR_UNUSED_HANDLER, + ZEND_FETCH_RW_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -45963,18 +40927,18 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_VAR_VAR_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_UNUSED_VAR_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER, ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_CV_TMP_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER, ZEND_FETCH_IS_SPEC_CONST_CONST_HANDLER, @@ -45982,15 +40946,15 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_IS_SPEC_CONST_VAR_HANDLER, ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_IS_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_IS_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_IS_SPEC_TMP_VAR_HANDLER, - ZEND_FETCH_IS_SPEC_TMP_UNUSED_HANDLER, + ZEND_FETCH_IS_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_IS_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_IS_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_IS_SPEC_VAR_VAR_HANDLER, - ZEND_FETCH_IS_SPEC_VAR_UNUSED_HANDLER, + ZEND_FETCH_IS_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -46028,28 +40992,28 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_TMP_CONST_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMP_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMP_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_VAR_VAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_VAR_CV_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_UNUSED_VAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CV_TMP_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER, ZEND_FETCH_FUNC_ARG_SPEC_CONST_CONST_HANDLER, @@ -46057,15 +41021,15 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_FUNC_ARG_SPEC_CONST_VAR_HANDLER, ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_FUNC_ARG_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_FUNC_ARG_SPEC_TMP_VAR_HANDLER, - ZEND_FETCH_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_FUNC_ARG_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_FUNC_ARG_SPEC_VAR_VAR_HANDLER, - ZEND_FETCH_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -46103,28 +41067,28 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER, ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMP_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMP_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER, ZEND_FETCH_UNSET_SPEC_CONST_CONST_HANDLER, @@ -46132,15 +41096,15 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_UNSET_SPEC_CONST_VAR_HANDLER, ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_UNSET_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_UNSET_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_UNSET_SPEC_TMP_VAR_HANDLER, - ZEND_FETCH_UNSET_SPEC_TMP_UNUSED_HANDLER, + ZEND_FETCH_UNSET_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_UNSET_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_UNSET_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_UNSET_SPEC_VAR_VAR_HANDLER, - ZEND_FETCH_UNSET_SPEC_VAR_UNUSED_HANDLER, + ZEND_FETCH_UNSET_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -46188,18 +41152,18 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER, ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER, ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER, ZEND_FETCH_LIST_SPEC_CONST_CONST_HANDLER, @@ -46558,28 +41522,28 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMP_TMPVAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMP_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER, ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER, ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER, ZEND_NULL_HANDLER, @@ -46588,8 +41552,8 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER, ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER, ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER, ZEND_NULL_HANDLER, @@ -46607,15 +41571,15 @@ void zend_init_opcodes_handlers(void) ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER, ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER, - ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_CONST_HANDLER, ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER, - ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -46628,28 +41592,28 @@ void zend_init_opcodes_handlers(void) ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMP_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMP_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CV_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMP_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CV_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMP_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CV_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMP_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER, ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER, @@ -47063,18 +42027,18 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_VAR_TMP_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_VAR_VAR_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER, ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMP_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_UNUSED_VAR_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HANDLER, ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_CV_TMP_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_CV_VAR_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER, ZEND_NULL_HANDLER, @@ -47088,18 +42052,18 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_PRE_DEC_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_VAR_TMP_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_VAR_VAR_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_PRE_DEC_OBJ_SPEC_VAR_CV_HANDLER, ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMP_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_UNUSED_VAR_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CV_HANDLER, ZEND_PRE_DEC_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_CV_TMP_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_CV_VAR_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_PRE_DEC_OBJ_SPEC_CV_CV_HANDLER, ZEND_NULL_HANDLER, @@ -47113,18 +42077,18 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_POST_INC_OBJ_SPEC_VAR_TMP_HANDLER, - ZEND_POST_INC_OBJ_SPEC_VAR_VAR_HANDLER, + ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER, ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_POST_INC_OBJ_SPEC_UNUSED_TMP_HANDLER, - ZEND_POST_INC_OBJ_SPEC_UNUSED_VAR_HANDLER, + ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HANDLER, ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_POST_INC_OBJ_SPEC_CV_TMP_HANDLER, - ZEND_POST_INC_OBJ_SPEC_CV_VAR_HANDLER, + ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER, ZEND_NULL_HANDLER, @@ -47138,18 +42102,18 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_POST_DEC_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_VAR_TMP_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_VAR_VAR_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_POST_DEC_OBJ_SPEC_VAR_CV_HANDLER, ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMP_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_UNUSED_VAR_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_POST_DEC_OBJ_SPEC_UNUSED_CV_HANDLER, ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_CV_TMP_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_CV_VAR_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_POST_DEC_OBJ_SPEC_CV_CV_HANDLER, ZEND_NULL_HANDLER, @@ -47163,18 +42127,18 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER, ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER, ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER, ZEND_NULL_HANDLER, @@ -47453,28 +42417,28 @@ void zend_init_opcodes_handlers(void) ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER, ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMP_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMP_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CV_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CV_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMP_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMP_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER, ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 45d1dd1b23..60d93d8bab 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -100,7 +100,7 @@ $op1_type = array( "CONST" => "IS_CONST", "UNUSED" => "IS_UNUSED", "CV" => "IS_CV", - "TMPVAR" => "???", + "TMPVAR" => "(IS_TMP_VAR|IS_VAR)", ); $op2_type = array( @@ -110,7 +110,7 @@ $op2_type = array( "CONST" => "IS_CONST", "UNUSED" => "IS_UNUSED", "CV" => "IS_CV", - "TMPVAR" => "???", + "TMPVAR" => "(IS_TMP_VAR|IS_VAR)", ); $op1_free = array( -- 2.40.0