From: Nikita Popov Date: Wed, 18 Mar 2020 13:52:22 +0000 (+0100) Subject: Revert "Fetch for read in nested property assignments" X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=df79277de35e096c654cf49b5e20960b3b8236c4;p=php Revert "Fetch for read in nested property assignments" This reverts commit bb43a3822e42dbd15b1d416a166549d3980b379a. After thinking about this a bit more, this is now going to be a complete solution for the "readonly properties" case, for example: unset($foo->readOnly->bar); should also be legal and $foo->readOnly['bar'] = 42; should also be legal if $foo->readOnly is not an array but an ArrayAccess object. I think it may be better to distinguish better on the BP_VAR flag level. Reverting for now. --- diff --git a/UPGRADING b/UPGRADING index 1467d311ad..a5984b4ea8 100644 --- a/UPGRADING +++ b/UPGRADING @@ -44,8 +44,8 @@ PHP 8.0 UPGRADE NOTES . Removed ability to use array_key_exists() with objects. Use one of isset() or property_exists() instead. . Made the behavior of array_key_exists() regarding the type of the key - parameter consistent with isset() and normal array access. All key types - now use the usual coercions and array/object keys throw a TypeError. + parameter consistent with isset() and normal array access. All key types now use + the usual coercions and array/object keys throw a TypeError. . Any array that has a number n as its first numeric key will use n+1 for its next implicit key. Even if n is negative. RFC: https://wiki.php.net/rfc/negative_array_index @@ -305,19 +305,6 @@ PHP 8.0 UPGRADE NOTES of the return value is not stable and may change between PHP versions. . Reflection export() methods have been removed. -- SimpleXML: - . It is no longer possible to perform deep initialization of SimpleXMLElement - objects: - - $x = simplexml_load_string(""); - $x->a->b->c = 'Test'; - // Error: Attempt to assign property 'c' of non-object - - The addChild() and addAttribute() APIs should be used instead. It is still - possible to modify already existing nodes by direct property assignment, - only the creation of multiple levels of nodes in one assignment is no longer - supported. - - Socket: . The deprecated AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES flags for socket_addrinfo_lookup() have been removed. diff --git a/Zend/tests/033.phpt b/Zend/tests/033.phpt index 31e7af42cd..652db2de20 100644 --- a/Zend/tests/033.phpt +++ b/Zend/tests/033.phpt @@ -15,6 +15,14 @@ try { echo $e->getMessage(), "\n"; } +$arr[][] = 2; + +try { + $arr[][]->bar = 2; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + ?> --EXPECTF-- Warning: Undefined variable: arr in %s on line %d @@ -54,16 +62,5 @@ Warning: Trying to access array offset on value of type null in %s on line %d Warning: Trying to access array offset on value of type null in %s on line %d Warning: Trying to get property 'foo' of non-object in %s on line %d - -Warning: Undefined variable: arr in %s on line %d - -Warning: Trying to access array offset on value of type null in %s on line %d - -Warning: Trying to access array offset on value of type null in %s on line %d - -Warning: Trying to access array offset on value of type null in %s on line %d - -Warning: Trying to access array offset on value of type null in %s on line %d - -Warning: Trying to access array offset on value of type null in %s on line %d Attempt to assign property 'foo' of non-object +Attempt to assign property 'bar' of non-object diff --git a/Zend/tests/bug41813.phpt b/Zend/tests/bug41813.phpt index b14e400d44..af73344f5d 100644 --- a/Zend/tests/bug41813.phpt +++ b/Zend/tests/bug41813.phpt @@ -9,7 +9,7 @@ $foo[0]->bar = "xyz"; echo "Done\n"; ?> --EXPECTF-- -Fatal error: Uncaught Error: Attempt to assign property 'bar' of non-object in %s:%d +Fatal error: Uncaught Error: Cannot use string offset as an object in %s:%d Stack trace: #0 {main} thrown in %s on line %d diff --git a/Zend/tests/bug41919.phpt b/Zend/tests/bug41919.phpt index 15bd399b78..2af13acdc9 100644 --- a/Zend/tests/bug41919.phpt +++ b/Zend/tests/bug41919.phpt @@ -8,9 +8,7 @@ $foo[3]->bar[1] = "bang"; echo "ok\n"; ?> --EXPECTF-- -Warning: Uninitialized string offset: 3 in %s on line %d - -Fatal error: Uncaught Error: Attempt to modify property 'bar' of non-object in %s:%d +Fatal error: Uncaught Error: Cannot use string offset as an object in %sbug41919.php:%d Stack trace: #0 {main} thrown in %sbug41919.php on line %d diff --git a/Zend/tests/bug47704.phpt b/Zend/tests/bug47704.phpt index 5375dbc339..4fdaba8092 100644 --- a/Zend/tests/bug47704.phpt +++ b/Zend/tests/bug47704.phpt @@ -6,7 +6,7 @@ $s = "abd"; $s[0]->a += 1; ?> --EXPECTF-- -Fatal error: Uncaught Error: Attempt to assign property 'a' of non-object in %s:%d +Fatal error: Uncaught Error: Cannot use string offset as an object in %sbug47704.php:%d Stack trace: #0 {main} thrown in %sbug47704.php on line %d diff --git a/Zend/tests/bug52041.phpt b/Zend/tests/bug52041.phpt index ab37203dcd..e5aca5c82e 100644 --- a/Zend/tests/bug52041.phpt +++ b/Zend/tests/bug52041.phpt @@ -51,25 +51,19 @@ Warning: Undefined variable: x in %s on line %d Attempt to assign property 'a' of non-object Warning: Undefined variable: x in %s on line %d - -Warning: Trying to get property 'a' of non-object in %s on line %d -Attempt to assign property 'b' of non-object +Attempt to modify property 'a' of non-object Warning: Undefined variable: x in %s on line %d Attempt to increment/decrement property 'a' of non-object Warning: Undefined variable: x in %s on line %d - -Warning: Trying to get property 'a' of non-object in %s on line %d -Attempt to increment/decrement property 'b' of non-object +Attempt to modify property 'a' of non-object Warning: Undefined variable: x in %s on line %d Attempt to assign property 'a' of non-object Warning: Undefined variable: x in %s on line %d - -Warning: Trying to get property 'a' of non-object in %s on line %d -Attempt to assign property 'b' of non-object +Attempt to modify property 'a' of non-object Warning: Undefined variable: x in %s on line %d diff --git a/Zend/tests/bug75921.phpt b/Zend/tests/bug75921.phpt index 11bab4b4ce..a8649262b5 100644 --- a/Zend/tests/bug75921.phpt +++ b/Zend/tests/bug75921.phpt @@ -53,29 +53,15 @@ Attempt to modify property 'a' of non-object Warning: Undefined variable: null in %s on line %d NULL - -Warning: Undefined variable: null in %s on line %d - -Warning: Trying to get property 'a' of non-object in %s on line %d -Attempt to assign property 'b' of non-object +Attempt to modify property 'a' of non-object Warning: Undefined variable: null in %s on line %d NULL - -Warning: Undefined variable: null in %s on line %d - -Warning: Trying to get property 'a' of non-object in %s on line %d - -Warning: Trying to access array offset on value of type null in %s on line %d -Attempt to assign property 'b' of non-object +Attempt to modify property 'a' of non-object Warning: Undefined variable: null in %s on line %d NULL - -Warning: Undefined variable: null in %s on line %d - -Warning: Trying to get property 'a' of non-object in %s on line %d -Attempt to modify property 'b' of non-object +Attempt to modify property 'a' of non-object Warning: Undefined variable: null in %s on line %d NULL diff --git a/Zend/tests/bug78531.phpt b/Zend/tests/bug78531.phpt index a8850fb8c2..1e8f0b34d1 100644 --- a/Zend/tests/bug78531.phpt +++ b/Zend/tests/bug78531.phpt @@ -34,6 +34,4 @@ Warning: Undefined variable: u3 in %s on line %d Attempt to increment/decrement property 'a' of non-object Warning: Undefined variable: u4 in %s on line %d - -Warning: Trying to get property 'a' of non-object in %s on line %d -Attempt to assign property 'a' of non-object +Attempt to modify property 'a' of non-object diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 9fa1f20f2d..2050e3ba71 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2703,13 +2703,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t } CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS; } else { - /* In $a->b->c = $d, fetch $a->b for read and only ->c for write. - * We will never modify $a->b itself, only the object it holds. */ - if (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_FUNC_ARG) { - opline = zend_delayed_compile_var(&obj_node, obj_ast, BP_VAR_R, 0); - } else { - opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0); - } + opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0); zend_separate_if_call_and_write(&obj_node, obj_ast, type); } zend_compile_expr(&prop_node, prop_ast); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 43b64cde62..68ef127ef6 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -989,7 +989,7 @@ ZEND_VM_COLD_HELPER(zend_undefined_function_helper, ANY, ANY) HANDLE_EXCEPTION(); } -ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP) +ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP) { USE_OPLINE zval *object; @@ -1002,7 +1002,7 @@ ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, zend_string *name, *tmp_name; SAVE_OPLINE(); - object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); + object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); property = GET_OP2_ZVAL_PTR(BP_VAR_R); do { @@ -1080,7 +1080,7 @@ ZEND_VM_C_LABEL(assign_op_object): FREE_OP_DATA(); FREE_OP2(); - FREE_OP1(); + FREE_OP1_VAR_PTR(); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -1248,7 +1248,7 @@ ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) +ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE zval *object; @@ -1260,7 +1260,7 @@ ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, C zend_string *name, *tmp_name; SAVE_OPLINE(); - object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); + object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); property = GET_OP2_ZVAL_PTR(BP_VAR_R); do { @@ -1312,7 +1312,7 @@ ZEND_VM_C_LABEL(pre_incdec_object): } while (0); FREE_OP2(); - FREE_OP1(); + FREE_OP1_VAR_PTR(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -1333,7 +1333,7 @@ ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CAC zend_string *name, *tmp_name; SAVE_OPLINE(); - object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); + object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); property = GET_OP2_ZVAL_PTR(BP_VAR_R); do { @@ -1384,7 +1384,7 @@ ZEND_VM_C_LABEL(post_incdec_object): } while (0); FREE_OP2(); - FREE_OP1(); + FREE_OP1_VAR_PTR(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2113,14 +2113,14 @@ ZEND_VM_C_LABEL(fetch_obj_r_finish): ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_WRITE|CACHE_SLOT) +ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_WRITE|CACHE_SLOT) { USE_OPLINE zval *property, *container, *result; SAVE_OPLINE(); - container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); + container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); property = GET_OP2_ZVAL_PTR(BP_VAR_R); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -2128,24 +2128,24 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FE ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); FREE_OP2(); - if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) { + if (OP1_TYPE == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) +ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE zval *property, *container, *result; SAVE_OPLINE(); - container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); + container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); property = GET_OP2_ZVAL_PTR(BP_VAR_R); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); FREE_OP2(); - if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) { + if (OP1_TYPE == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -2262,7 +2262,7 @@ ZEND_VM_C_LABEL(fetch_obj_is_finish): ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|CACHE_SLOT) +ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|CACHE_SLOT) { #if !ZEND_VM_SPEC USE_OPLINE @@ -2270,7 +2270,7 @@ ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMPVAR|UNUSED|THIS if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if (OP1_TYPE == IS_CONST) { + if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_DISPATCH_TO_HELPER(zend_use_tmp_in_write_context_helper); } ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_OBJ_W); @@ -2331,7 +2331,7 @@ ZEND_VM_HANDLER(155, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV)) +ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV)) { USE_OPLINE zval *object, *property, *value, tmp; @@ -2339,7 +2339,7 @@ ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CAC zend_string *name, *tmp_name; SAVE_OPLINE(); - object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); + object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); property = GET_OP2_ZVAL_PTR(BP_VAR_R); value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); @@ -2470,7 +2470,7 @@ ZEND_VM_C_LABEL(free_and_exit_assign_obj): FREE_OP_DATA(); ZEND_VM_C_LABEL(exit_assign_obj): FREE_OP2(); - FREE_OP1(); + FREE_OP1_VAR_PTR(); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -2676,14 +2676,14 @@ ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT|SRC, SPEC(OP_DATA=VAR|CV)) +ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT|SRC, SPEC(OP_DATA=VAR|CV)) { USE_OPLINE zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); + container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); property = GET_OP2_ZVAL_PTR(BP_VAR_R); value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W); @@ -2706,7 +2706,7 @@ ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, zend_assign_to_property_reference(container, OP1_TYPE, property, OP2_TYPE, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - FREE_OP1(); + FREE_OP1_VAR_PTR(); FREE_OP2(); FREE_OP_DATA_VAR_PTR(); ZEND_VM_NEXT_OPCODE_EX(1, 2); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 683db7cf82..f7155da46f 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -5434,7 +5434,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if (IS_CONST == IS_CONST) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -7609,7 +7609,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if (IS_CONST == IS_CONST) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -9865,7 +9865,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if (IS_CONST == IS_CONST) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -13897,170 +13897,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HAN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *object; - zval *property; - zval *value; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - - do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_op_object; - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; - } - -assign_op_object: - /* here we are sure we are dealing with an object */ - zobj = Z_OBJ_P(object); - if (IS_CONST == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - UNDEF_RESULT(); - break; - } - } - cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - zval *orig_zptr = zptr; - zend_reference *ref; - - do { - if (UNEXPECTED(Z_ISREF_P(zptr))) { - ref = Z_REF_P(zptr); - zptr = Z_REFVAL_P(zptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - } - - if (IS_CONST == IS_CONST) { - prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr); - } - if (UNEXPECTED(prop_info)) { - /* special case for typed properties */ - zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_binary_op(zptr, zptr, value OPLINE_CC); - } - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } else { - zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); - } - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - } while (0); - - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); -} - -/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - - do { - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto pre_incdec_object; - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; - } - -pre_incdec_object: - /* here we are sure we are dealing with an object */ - zobj = Z_OBJ_P(object); - if (IS_CONST == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - UNDEF_RESULT(); - break; - } - } - cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - if (IS_CONST == IS_CONST) { - prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); - } - zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); - } - } else { - zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); - } - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - } while (0); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -14230,44 +14066,6 @@ fetch_obj_r_finish: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *property, *container, *result; - - SAVE_OPLINE(); - - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - result = EX_VAR(opline->result.var); - zend_fetch_property_address( - result, container, (IS_TMP_VAR|IS_VAR), property, IS_CONST, - ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), - BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *property, *container, *result; - - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - result = EX_VAR(opline->result.var); - zend_fetch_property_address(result, container, (IS_TMP_VAR|IS_VAR), property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -14379,694 +14177,676 @@ fetch_obj_is_finish: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 USE_OPLINE -#endif + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - /* Behave like FETCH_OBJ_W */ - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + op1_str = zval_get_string_func(op1); + } + if (IS_CONST == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); } + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - value = RT_CONSTANT((opline+1), (opline+1)->op1); - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + if (IS_CONST != IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); } -assign_object: - zobj = Z_OBJ_P(object); - if (IS_CONST == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; - - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; - - if (IS_CONST == IS_CONST) { - orig_type = Z_TYPE_P(value); - } - - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_CONST == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } - } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } } + zend_throw_error(NULL, "Method name must be a string"); - if (!zobj->ce->__set) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } while (0); + } - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; } - } else if (IS_CONST != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_CONST == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CONST != IS_CONST) { + } - } else if (IS_CONST == IS_CV) { - Z_TRY_ADDREF_P(value); + HANDLE_EXCEPTION(); } } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (IS_CONST == IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); } - goto exit_assign_obj; + zend_invalid_method_call(object, function_name); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } - } + } while (0); } - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - ZVAL_DEREF(value); - } + obj = Z_OBJ_P(object); + called_scope = obj->ce; - if (IS_CONST == IS_CONST) { - name = Z_STR_P(property); + if (IS_CONST == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { + zend_object *orig_obj = obj; - UNDEF_RESULT(); - goto exit_assign_obj; + if (IS_CONST == IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); } - } - value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(obj->ce, Z_STR_P(function_name)); + } - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + if (IS_CONST == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + /* Reset "object" to trigger reference counting */ + object = NULL; + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } } -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } + if (IS_CONST != IS_CONST) { -exit_assign_obj: + } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); -} + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *op1, *op2; + double d1, d2; - SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +case_true: + ZEND_VM_SMART_BRANCH_TRUE(); + } else { +case_false: + ZEND_VM_SMART_BRANCH_FALSE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto case_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +case_double: + if (d1 == d2) { + goto case_true; + } else { + goto case_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto case_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; + if (result) { + goto case_true; + } else { + goto case_false; + } } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; } + ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} -assign_object: - zobj = Z_OBJ_P(object); - if (IS_CONST == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; - - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zend_ulong hval; + zval *offset; - if (IS_TMP_VAR == IS_CONST) { - orig_type = Z_TYPE_P(value); - } + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = RT_CONSTANT(opline, opline->op2); - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_TMP_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +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; } } + value = zend_hash_find_ex_ind(ht, str, IS_CONST == IS_CONST); + } 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 if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; - } + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; } + } - if (!zobj->ce->__set) { + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > 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); - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } else if (IS_TMP_VAR != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_TMP_VAR == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else if (IS_TMP_VAR == IS_CV) { - Z_TRY_ADDREF_P(value); - } - } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { + /* avoid exception check */ + + ZEND_VM_SMART_BRANCH(result, 0); } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; } } - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(value); + if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; } - - if (IS_CONST == IS_CONST) { - name = Z_STR_P(property); + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; - } - } - - value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); } -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: +isset_dim_obj_exit: zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_SMART_BRANCH(result, 1); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; + zval *container; + int result; + zval *offset; zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } - -assign_object: - zobj = Z_OBJ_P(object); - if (IS_CONST == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; - - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; - - if (IS_VAR == IS_CONST) { - orig_type = Z_TYPE_P(value); - } - - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = RT_CONSTANT(opline, opline->op2); - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; } } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; - } - } - - if (!zobj->ce->__set) { - - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } else if (IS_VAR != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_VAR == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else if (IS_VAR == IS_CV) { - Z_TRY_ADDREF_P(value); - } - } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; } } - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(value); - } - if (IS_CONST == IS_CONST) { - name = Z_STR_P(property); + name = Z_STR_P(offset); } else { - name = zval_try_get_tmp_string(property, &tmp_name); + name = zval_try_get_tmp_string(offset, &tmp_name); if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; + result = 0; + goto isset_object_finish; } } - value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); if (IS_CONST != IS_CONST) { zend_tmp_string_release(tmp_name); } -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: +isset_object_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_SMART_BRANCH(result, 1); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + + zval *key, *subject; + HashTable *ht; + zend_bool result; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + subject = RT_CONSTANT(opline, opline->op2); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } -assign_object: - zobj = Z_OBJ_P(object); - if (IS_CONST == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; - - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; +/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + zend_bool result; - if (IS_CV == IS_CONST) { - orig_type = Z_TYPE_P(value); - } + SAVE_OPLINE(); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_CV == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + if (IS_CONST == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (EXPECTED(ce)) { + CACHE_PTR(opline->extended_value, ce); } } - } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; - } + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = ce && instanceof_function(Z_OBJCE_P(expr), ce); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { + expr = Z_REFVAL_P(expr); + goto try_instanceof; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + result = 0; + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} - if (!zobj->ce->__set) { +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + zend_long offset; + HashTable *ht; - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } else if (IS_CV != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_CV == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else if (IS_CV == IS_CV) { - Z_TRY_ADDREF_P(value); - } - } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = RT_CONSTANT(opline, opline->op2); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_index_array: + if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { + offset = Z_LVAL_P(dim); + } else { + offset = zval_get_long(dim); + } + ht = Z_ARRVAL_P(container); + ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + SAVE_OPLINE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_index_array; + } else { + goto fetch_dim_r_index_slow; } - } - - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(value); - } - - if (IS_CONST == IS_CONST) { - name = Z_STR_P(property); } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - - UNDEF_RESULT(); - goto exit_assign_obj; +fetch_dim_r_index_slow: + SAVE_OPLINE(); + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } - value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - -exit_assign_obj: - +fetch_dim_r_index_undef: + ZVAL_NULL(EX_VAR(opline->result.var)); + SAVE_OPLINE(); + zend_undefined_offset(offset); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; - - SAVE_OPLINE(); + zval *container, *dim, *value; + zend_long offset; + HashTable *ht; container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - - if (1) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - if (IS_CONST == IS_CONST) { - zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } + dim = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_index_array: + if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { + offset = Z_LVAL_P(dim); } else { - if (IS_CONST == IS_CONST) { - zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } + offset = zval_get_long(dim); + } + ht = Z_ARRVAL_P(container); + ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + SAVE_OPLINE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_index_array; + } else { + goto fetch_dim_r_index_slow; } } else { - zend_assign_to_property_reference(container, (IS_TMP_VAR|IS_VAR), property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); +fetch_dim_r_index_slow: + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +fetch_dim_r_index_undef: + ZVAL_NULL(EX_VAR(opline->result.var)); + SAVE_OPLINE(); + zend_undefined_offset(offset); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; + zval *op1, *op2; SAVE_OPLINE(); - - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - - value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); - - if (1) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - if (IS_CONST == IS_CONST) { - zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } - } else { - if (IS_CONST == IS_CONST) { - zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } - } - } else { - zend_assign_to_property_reference(container, (IS_TMP_VAR|IS_VAR), property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } - + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + fast_div_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; - ZEND_VM_NEXT_OPCODE_EX(1, 2); + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + pow_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - zend_string *op1_str, *op2_str, *str; - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = RT_CONSTANT(opline, opline->op2); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && - (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { zend_string *op1_str = Z_STR_P(op1); zend_string *op2_str = Z_STR_P(op2); zend_string *str; if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); @@ -15074,13 +14854,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op1_str, 0); } - } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && @@ -15090,7 +14870,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } else { @@ -15101,681 +14881,144 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op1_str, 0); } - if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } ZEND_VM_NEXT_OPCODE(); - } - - SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - op1_str = Z_STR_P(op1); - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - op1_str = zend_string_copy(Z_STR_P(op1)); } else { + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + op1 = ZVAL_UNDEFINED_OP1(); } - op1_str = zval_get_string_func(op1); - } - if (IS_CONST == IS_CONST) { - op2_str = Z_STR_P(op2); - } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - op2_str = zend_string_copy(Z_STR_P(op2)); - } else { - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); } - op2_str = zval_get_string_func(op2); + concat_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } - do { - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { - GC_ADDREF(op2_str); - } - } - ZVAL_STR(EX_VAR(opline->result.var), op2_str); - zend_string_release_ex(op1_str, 0); - break; - } - } - if (IS_CONST != IS_CONST) { - if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { - GC_ADDREF(op1_str); - } - } - ZVAL_STR(EX_VAR(opline->result.var), op1_str); - zend_string_release_ex(op2_str, 0); - break; - } - } - str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); - memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); - memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); - ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_string_release_ex(op1_str, 0); - } - if (IS_CONST != IS_CONST) { - zend_string_release_ex(op2_str, 0); - } - } while (0); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; - zend_execute_data *call; - uint32_t call_info; - - SAVE_OPLINE(); - - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CONST != IS_CONST) { - function_name = RT_CONSTANT(opline, opline->op2); - } - - if (IS_CONST != IS_CONST && - UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - do { - if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { - function_name = Z_REFVAL_P(function_name); - if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { - break; - } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - } - zend_throw_error(NULL, "Method name must be a string"); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } while (0); - } - - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - do { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - object = ZVAL_UNDEFINED_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_CONST != IS_CONST) { - - } - HANDLE_EXCEPTION(); - } - } - if (IS_CONST == IS_CONST) { - function_name = RT_CONSTANT(opline, opline->op2); - } - zend_invalid_method_call(object, function_name); + zval *op1, *op2; + double d1, d2; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } - } while (0); - } - - obj = Z_OBJ_P(object); - called_scope = obj->ce; - - if (IS_CONST == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); - } else { - zend_object *orig_obj = obj; - - if (IS_CONST == IS_CONST) { - function_name = RT_CONSTANT(opline, opline->op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; } - - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); - if (UNEXPECTED(fbc == NULL)) { - if (EXPECTED(!EG(exception))) { - zend_undefined_method(obj->ce, Z_STR_P(function_name)); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - if (IS_CONST == IS_CONST && - EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && - EXPECTED(obj == orig_obj)) { - CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); - } - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; - } - if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { - init_func_run_time_cache(&fbc->op_array); - } - } - - if (IS_CONST != IS_CONST) { - - } - - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; } - /* call static method */ - obj = (zend_object*)called_scope; - call_info = ZEND_CALL_NESTED_FUNCTION; - } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV) { - GC_ADDREF(obj); /* For $this pointer */ - } else { - zval *free_op1 = EX_VAR(opline->op1.var); - if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - zval_ptr_dtor_nogc(free_op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; } } - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } - - call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, obj); - call->prev_execute_data = EX(call); - EX(call) = call; - - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; double d1, d2; op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = RT_CONSTANT(opline, opline->op2); - if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { -case_true: - ZEND_VM_SMART_BRANCH_TRUE(); +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); } else { -case_false: - ZEND_VM_SMART_BRANCH_FALSE(); +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); d2 = Z_DVAL_P(op2); - goto case_double; + goto is_equal_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = Z_DVAL_P(op1); d2 = Z_DVAL_P(op2); -case_double: +is_equal_double: if (d1 == d2) { - goto case_true; + goto is_equal_true; } else { - goto case_false; + goto is_equal_false; } } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { d1 = Z_DVAL_P(op1); d2 = (double)Z_LVAL_P(op2); - goto case_double; + goto is_equal_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } if (result) { - goto case_true; + goto is_equal_true; } else { - goto case_false; + goto is_equal_false; } } } - ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - int result; - zend_ulong hval; - zval *offset; - - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = RT_CONSTANT(opline, opline->op2); - - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; - zval *value; - zend_string *str; - -isset_dim_obj_array: - ht = Z_ARRVAL_P(container); -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; - } - } - value = zend_hash_find_ex_ind(ht, str, IS_CONST == IS_CONST); - } 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 if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { - offset = Z_REFVAL_P(offset); - goto isset_again; - } else { - value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); - if (UNEXPECTED(EG(exception))) { - result = 0; - goto isset_dim_obj_exit; - } - } - - if (!(opline->extended_value & ZEND_ISEMPTY)) { - /* > 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); - - if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { - /* avoid exception check */ - - ZEND_VM_SMART_BRANCH(result, 0); - } - } else { - result = (value == NULL || !i_zend_is_true(value)); - } - goto isset_dim_obj_exit; - } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto isset_dim_obj_array; - } - } - - if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { - offset++; - } - if (!(opline->extended_value & ZEND_ISEMPTY)) { - result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); - } else { - result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); - } - -isset_dim_obj_exit: - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - int result; - zval *offset; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = RT_CONSTANT(opline, opline->op2); - - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || - ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { - result = (opline->extended_value & ZEND_ISEMPTY); - goto isset_object_finish; - } - } else { - result = (opline->extended_value & ZEND_ISEMPTY); - goto isset_object_finish; - } - } - - if (IS_CONST == IS_CONST) { - name = Z_STR_P(offset); - } else { - name = zval_try_get_tmp_string(offset, &tmp_name); - if (UNEXPECTED(!name)) { - result = 0; - goto isset_object_finish; - } - } - - result = - (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); - - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - -isset_object_finish: - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *key, *subject; - HashTable *ht; - zend_bool result; - - SAVE_OPLINE(); - - key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - subject = RT_CONSTANT(opline, opline->op2); - - if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { -array_key_exists_array: - ht = Z_ARRVAL_P(subject); - result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); - } else { - if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { - subject = Z_REFVAL_P(subject); - if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { - goto array_key_exists_array; - } - } - zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); - result = 0; - } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} - -/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *expr; - zend_bool result; - - SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - -try_instanceof: - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; - - if (IS_CONST == IS_CONST) { - ce = CACHED_PTR(opline->extended_value); - if (UNEXPECTED(ce == NULL)) { - ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); - if (EXPECTED(ce)) { - CACHE_PTR(opline->extended_value, ce); - } - } - } else if (IS_CONST == IS_UNUSED) { - ce = zend_fetch_class(NULL, opline->op2.num); - if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); - } - result = ce && instanceof_function(Z_OBJCE_P(expr), ce); - } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { - expr = Z_REFVAL_P(expr); - goto try_instanceof; - } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - result = 0; - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *dim, *value; - zend_long offset; - HashTable *ht; - - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - dim = RT_CONSTANT(opline, opline->op2); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { -fetch_dim_r_index_array: - if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { - offset = Z_LVAL_P(dim); - } else { - offset = zval_get_long(dim); - } - ht = Z_ARRVAL_P(container); - ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - SAVE_OPLINE(); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - ZEND_VM_NEXT_OPCODE(); - } - } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto fetch_dim_r_index_array; - } else { - goto fetch_dim_r_index_slow; - } - } else { -fetch_dim_r_index_slow: - SAVE_OPLINE(); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - -fetch_dim_r_index_undef: - ZVAL_NULL(EX_VAR(opline->result.var)); - SAVE_OPLINE(); - zend_undefined_offset(offset); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *dim, *value; - zend_long offset; - HashTable *ht; - - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - dim = EX_VAR(opline->op2.var); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { -fetch_dim_r_index_array: - if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { - offset = Z_LVAL_P(dim); - } else { - offset = zval_get_long(dim); - } - ht = Z_ARRVAL_P(container); - ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - SAVE_OPLINE(); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - ZEND_VM_NEXT_OPCODE(); - } - } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto fetch_dim_r_index_array; - } else { - goto fetch_dim_r_index_slow; - } - } else { -fetch_dim_r_index_slow: - SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - -fetch_dim_r_index_undef: - ZVAL_NULL(EX_VAR(opline->result.var)); - SAVE_OPLINE(); - zend_undefined_offset(offset); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - - if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && - ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { - zend_string *op1_str = Z_STR_P(op1); - zend_string *op2_str = Z_STR_P(op2); - zend_string *str; - - if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); - } else { - ZVAL_STR(EX_VAR(opline->result.var), op2_str); - } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op1_str, 0); - } - } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); - } else { - ZVAL_STR(EX_VAR(opline->result.var), op1_str); - } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op2_str, 0); - } - } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && - !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); - - str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); - memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); - ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op2_str, 0); - } - } else { - str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); - memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); - memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); - ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op1_str, 0); - } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op2_str, 0); - } - } - ZEND_VM_NEXT_OPCODE(); - } else { - SAVE_OPLINE(); - - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - op1 = ZVAL_UNDEFINED_OP1(); - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { - op2 = ZVAL_UNDEFINED_OP2(); - } - concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15789,10 +15032,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HA if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - ZEND_VM_SMART_BRANCH_TRUE_NONE(); + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); } else { is_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_NONE(); + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15833,7 +15076,7 @@ is_equal_double: ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15845,32 +15088,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JM /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { -is_equal_true: - ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { -is_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); d2 = Z_DVAL_P(op2); - goto is_equal_double; + goto is_not_equal_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = Z_DVAL_P(op1); d2 = Z_DVAL_P(op2); -is_equal_double: - if (d1 == d2) { - goto is_equal_true; +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; } else { - goto is_equal_false; + goto is_not_equal_false; } } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { d1 = Z_DVAL_P(op1); d2 = (double)Z_LVAL_P(op2); - goto is_equal_double; + goto is_not_equal_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { @@ -15881,17 +15124,17 @@ is_equal_double: if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op2); } - if (result) { - goto is_equal_true; + if (!result) { + goto is_not_equal_true; } else { - goto is_equal_false; + goto is_not_equal_false; } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15903,32 +15146,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JM /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { -is_equal_true: - ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); } else { -is_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); d2 = Z_DVAL_P(op2); - goto is_equal_double; + goto is_not_equal_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = Z_DVAL_P(op1); d2 = Z_DVAL_P(op2); -is_equal_double: - if (d1 == d2) { - goto is_equal_true; +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; } else { - goto is_equal_false; + goto is_not_equal_false; } } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { d1 = Z_DVAL_P(op1); d2 = (double)Z_LVAL_P(op2); - goto is_equal_double; + goto is_not_equal_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { @@ -15939,17 +15182,17 @@ is_equal_double: if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op2); } - if (result) { - goto is_equal_true; + if (!result) { + goto is_not_equal_true; } else { - goto is_equal_false; + goto is_not_equal_false; } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15963,10 +15206,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - ZEND_VM_SMART_BRANCH_TRUE_NONE(); + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); } else { is_not_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_NONE(); + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -16007,128 +15250,12 @@ is_not_equal_double: ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { - /* pass */ - } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { -is_not_equal_true: - ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - } else { -is_not_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = (double)Z_LVAL_P(op1); - d2 = Z_DVAL_P(op2); - goto is_not_equal_double; - } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = Z_DVAL_P(op1); - d2 = Z_DVAL_P(op2); -is_not_equal_double: - if (d1 != d2) { - goto is_not_equal_true; - } else { - goto is_not_equal_false; - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - d1 = Z_DVAL_P(op1); - d2 = (double)Z_LVAL_P(op2); - goto is_not_equal_double; - } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op1); - } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op2); - } - if (!result) { - goto is_not_equal_true; - } else { - goto is_not_equal_false; - } - } - } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - double d1, d2; - - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { - /* pass */ - } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { -is_not_equal_true: - ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - } else { -is_not_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = (double)Z_LVAL_P(op1); - d2 = Z_DVAL_P(op2); - goto is_not_equal_double; - } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = Z_DVAL_P(op1); - d2 = Z_DVAL_P(op2); -is_not_equal_double: - if (d1 != d2) { - goto is_not_equal_true; - } else { - goto is_not_equal_false; - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - d1 = Z_DVAL_P(op1); - d2 = (double)Z_LVAL_P(op2); - goto is_not_equal_double; - } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op1); - } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op2); - } - if (!result) { - goto is_not_equal_true; - } else { - goto is_not_equal_false; - } - } - } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - - SAVE_OPLINE(); + SAVE_OPLINE(); op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); @@ -16151,171 +15278,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *object; - zval *property; - zval *value; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - - do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_op_object; - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; - } - -assign_op_object: - /* here we are sure we are dealing with an object */ - zobj = Z_OBJ_P(object); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - UNDEF_RESULT(); - break; - } - } - cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - zval *orig_zptr = zptr; - zend_reference *ref; - - do { - if (UNEXPECTED(Z_ISREF_P(zptr))) { - ref = Z_REF_P(zptr); - zptr = Z_REFVAL_P(zptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - } - - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr); - } - if (UNEXPECTED(prop_info)) { - /* special case for typed properties */ - zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_binary_op(zptr, zptr, value OPLINE_CC); - } - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } else { - zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); - } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - } while (0); - - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); -} - -/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - - do { - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto pre_incdec_object; - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; - } - -pre_incdec_object: - /* here we are sure we are dealing with an object */ - zobj = Z_OBJ_P(object); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - UNDEF_RESULT(); - break; - } - } - cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); - } - zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); - } - } else { - zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); - } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - } while (0); - - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -16485,44 +15447,6 @@ fetch_obj_r_finish: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *property, *container, *result; - - SAVE_OPLINE(); - - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - result = EX_VAR(opline->result.var); - zend_fetch_property_address( - result, container, (IS_TMP_VAR|IS_VAR), property, (IS_TMP_VAR|IS_VAR), - (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), - BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *property, *container, *result; - - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - result = EX_VAR(opline->result.var); - zend_fetch_property_address(result, container, (IS_TMP_VAR|IS_VAR), property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -16634,694 +15558,932 @@ fetch_obj_is_finish: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 USE_OPLINE -#endif + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - /* Behave like FETCH_OBJ_W */ - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + op1_str = zval_get_string_func(op1); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); } + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = RT_CONSTANT((opline+1), (opline+1)->op1); - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } -assign_object: - zobj = Z_OBJ_P(object); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; - - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; - - if (IS_CONST == IS_CONST) { - orig_type = Z_TYPE_P(value); - } - - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } while (0); + } - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_CONST == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; } - goto exit_assign_obj; } - } - } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + HANDLE_EXCEPTION(); } - zobj->properties = zend_array_dup(zobj->properties); } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } + zend_invalid_method_call(object, function_name); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } + } while (0); + } - if (!zobj->ce->__set) { + obj = Z_OBJ_P(object); + called_scope = obj->ce; - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } else if (IS_CONST != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_CONST == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else if (IS_CONST == IS_CV) { - Z_TRY_ADDREF_P(value); - } - } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + zend_object *orig_obj = obj; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(obj->ce, Z_STR_P(function_name)); } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + /* Reset "object" to trigger reference counting */ + object = NULL; + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); } } - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - ZVAL_DEREF(value); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } - value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; -exit_assign_obj: - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zval *op1, *op2; + double d1, d2; - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +case_true: + ZEND_VM_SMART_BRANCH_TRUE(); + } else { +case_false: + ZEND_VM_SMART_BRANCH_FALSE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto case_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +case_double: + if (d1 == d2) { + goto case_true; + } else { + goto case_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto case_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (result) { + goto case_true; + } else { + goto case_false; + } } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; } + ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} -assign_object: - zobj = Z_OBJ_P(object); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; - - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zend_ulong hval; + zval *offset; - if (IS_TMP_VAR == IS_CONST) { - orig_type = Z_TYPE_P(value); - } + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_TMP_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +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; } } + value = zend_hash_find_ex_ind(ht, str, (IS_TMP_VAR|IS_VAR) == IS_CONST); + } 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 if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; - } + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; } + } - if (!zobj->ce->__set) { + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > 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); - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } else if (IS_TMP_VAR != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_TMP_VAR == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else if (IS_TMP_VAR == IS_CV) { - Z_TRY_ADDREF_P(value); - } - } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { + /* avoid exception check */ + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; } } - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(value); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; } - - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(property); + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; - } - } - - value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); } -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: +isset_dim_obj_exit: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_SMART_BRANCH(result, 1); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; + zval *container; + int result; + zval *offset; zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } - -assign_object: - zobj = Z_OBJ_P(object); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; - - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; - - if (IS_VAR == IS_CONST) { - orig_type = Z_TYPE_P(value); - } - - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; } } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; - } - } - - if (!zobj->ce->__set) { - - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } else if (IS_VAR != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_VAR == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else if (IS_VAR == IS_CV) { - Z_TRY_ADDREF_P(value); - } - } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; } } - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(value); - } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(property); + name = Z_STR_P(offset); } else { - name = zval_try_get_tmp_string(property, &tmp_name); + name = zval_try_get_tmp_string(offset, &tmp_name); if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; + result = 0; + goto isset_object_finish; } } - value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_tmp_string_release(tmp_name); } -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: +isset_object_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_SMART_BRANCH(result, 1); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + + zval *key, *subject; + HashTable *ht; + zend_bool result; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } -assign_object: - zobj = Z_OBJ_P(object); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; - - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; +/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + zend_bool result; - if (IS_CV == IS_CONST) { - orig_type = Z_TYPE_P(value); - } + SAVE_OPLINE(); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_CV == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + if (IS_VAR == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (EXPECTED(ce)) { + CACHE_PTR(opline->extended_value, ce); } } - } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; - } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = ce && instanceof_function(Z_OBJCE_P(expr), ce); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { + expr = Z_REFVAL_P(expr); + goto try_instanceof; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + result = 0; + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} - if (!zobj->ce->__set) { +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) +{ + USE_OPLINE + zval *varname; + zval *retval; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } else if (IS_CV != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_CV == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else if (IS_CV == IS_CV) { - Z_TRY_ADDREF_P(value); - } - } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + SAVE_OPLINE(); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + 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); + tmp_name = NULL; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + retval = zend_hash_find_ex(target_symbol_table, name, (IS_TMP_VAR|IS_VAR) == IS_CONST); + if (retval == NULL) { + if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { +fetch_this: + zend_fetch_this_var(type OPLINE_CC EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + if (type == BP_VAR_W) { + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + } else if (type == BP_VAR_IS) { + retval = &EG(uninitialized_zval); + } else { + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); + if (type == BP_VAR_RW) { + retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); + } else { + retval = &EG(uninitialized_zval); + } + } + /* 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) { + if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { + goto fetch_this; + } + if (type == BP_VAR_W) { + ZVAL_NULL(retval); + } else if (type == BP_VAR_IS) { + retval = &EG(uninitialized_zval); + } else { + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); + if (type == BP_VAR_RW) { + ZVAL_NULL(retval); + } else { + retval = &EG(uninitialized_zval); } - goto exit_assign_obj; } } } - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(value); + if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + int fetch_type = + (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? + BP_VAR_W : BP_VAR_R; + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(fetch_type ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varname; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(property); + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + tmp_name = NULL; } else { - name = zval_try_get_tmp_string(property, &tmp_name); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = ZVAL_UNDEFINED_OP1(); + } + name = zval_try_get_tmp_string(varname, &tmp_name); if (UNEXPECTED(!name)) { - - UNDEF_RESULT(); - goto exit_assign_obj; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } } - value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + zend_hash_del_ind(target_symbol_table, name); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_tmp_string_release(tmp_name); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + int result; + zval *varname; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(varname); + } else { + name = zval_get_tmp_string(varname, &tmp_name); } -exit_assign_obj: - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + value = zend_hash_find_ex(target_symbol_table, name, (IS_TMP_VAR|IS_VAR) == IS_CONST); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + + if (!value) { + result = (opline->extended_value & ZEND_ISEMPTY); + } else { + if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + if (Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + } + result = Z_TYPE_P(value) > IS_NULL; + } else { + result = !i_zend_is_true(value); + } + } + + ZEND_VM_SMART_BRANCH(result, 1); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; + zval *expr; + zend_bool result; SAVE_OPLINE(); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; - if (1) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + if (IS_UNUSED == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (EXPECTED(ce)) { + CACHE_PTR(opline->extended_value, ce); + } } - } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); } + result = ce && instanceof_function(Z_OBJCE_P(expr), ce); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { + expr = Z_REFVAL_P(expr); + goto try_instanceof; } else { - zend_assign_to_property_reference(container, (IS_TMP_VAR|IS_VAR), property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + result = 0; } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_SMART_BRANCH(result, 1); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; + zval *op1; + zend_long count; SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + while (1) { + if (Z_TYPE_P(op1) == IS_ARRAY) { + count = zend_array_count(Z_ARRVAL_P(op1)); + break; + } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + /* first, we check if the handler is defined */ + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { + break; + } + if (UNEXPECTED(EG(exception))) { + count = 0; + break; + } + } - value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + /* if not and the object implements Countable we call its count() method */ + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { + zval retval; - if (1) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); + count = zval_get_long(&retval); + zval_ptr_dtor(&retval); + break; + } + + /* If There's no handler and it doesn't implement Countable then add a warning */ + count = 1; + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + continue; + } else if (Z_TYPE_P(op1) <= IS_NULL) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } + count = 0; } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + count = 1; + } + zend_error(E_WARNING, "%s(): Parameter must be an array or an object that implements Countable", opline->extended_value ? "sizeof" : "count"); + break; + } + + ZVAL_LONG(EX_VAR(opline->result.var), count); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (UNEXPECTED(!EX(func)->common.scope)) { + SAVE_OPLINE(); + zend_error(E_WARNING, "get_class() called without object from outside a class"); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); + ZEND_VM_NEXT_OPCODE(); + } + } else { + zval *op1; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + while (1) { + if (Z_TYPE_P(op1) == IS_OBJECT) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + continue; } else { - zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } + break; } - } else { - zend_assign_to_property_reference(container, (IS_TMP_VAR|IS_VAR), property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zval *result = EX_VAR(opline->result.var); + ZVAL_COPY(result, value); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + fast_div_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - zend_string *op1_str, *op2_str, *str; + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + pow_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + op2 = EX_VAR(opline->op2.var); + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && - ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { zend_string *op1_str = Z_STR_P(op1); zend_string *op2_str = Z_STR_P(op2); zend_string *str; if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); @@ -17329,13 +16491,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op1_str, 0); } - } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && @@ -17345,7 +16507,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } else { @@ -17356,7 +16518,373 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op1_str, 0); } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } else { + SAVE_OPLINE(); + + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); + } + concat_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + compare_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = EX_VAR(opline->op2.var); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = EX_VAR(opline->op2.var); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + do { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + zend_wrong_property_read(offset); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (EXPECTED(zobj->properties != NULL)) { + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); + + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name))))) { + retval = &p->val; + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_ex(zobj->properties, name, 1); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + do { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + break; + } + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (EXPECTED(zobj->properties != NULL)) { + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); + + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name))))) { + retval = &p->val; + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_ex(zobj->properties, name, 1); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = EX_VAR(opline->op2.var); + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } @@ -17374,12 +16902,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR } op1_str = zval_get_string_func(op1); } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (IS_CV == IS_CONST) { op2_str = Z_STR_P(op2); } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { op2_str = zend_string_copy(Z_STR_P(op2)); } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } op2_str = zval_get_string_func(op2); @@ -17387,7 +16915,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR do { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { GC_ADDREF(op2_str); } @@ -17397,7 +16925,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR break; } } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (IS_CV != IS_CONST) { if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { @@ -17416,16 +16944,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_string_release_ex(op1_str, 0); } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (IS_CV != IS_CONST) { zend_string_release_ex(op2_str, 0); } } while (0); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -17440,19 +16968,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (IS_CV != IS_CONST) { + function_name = EX_VAR(opline->op2.var); } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { break; } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -17460,7 +16988,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } while (0); @@ -17478,17 +17006,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { object = ZVAL_UNDEFINED_OP1(); if (UNEXPECTED(EG(exception) != NULL)) { - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CV != IS_CONST) { + } HANDLE_EXCEPTION(); } } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } @@ -17498,27 +17026,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T obj = Z_OBJ_P(object); called_scope = obj->ce; - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + if (IS_CV == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { zend_object *orig_obj = obj; - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); } /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + if (IS_CV == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -17532,8 +17060,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T } } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CV != IS_CONST) { + } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -17568,14 +17096,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; double d1, d2; op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + op2 = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { @@ -17608,7 +17136,7 @@ case_double: } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (result) { goto case_true; } else { @@ -17619,7 +17147,7 @@ case_double: ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -17629,7 +17157,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + offset = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -17641,17 +17169,17 @@ isset_dim_obj_array: isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (IS_CV != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index_prop; } } - value = zend_hash_find_ex_ind(ht, str, (IS_TMP_VAR|IS_VAR) == IS_CONST); + value = zend_hash_find_ex_ind(ht, str, IS_CV == IS_CONST); } 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 if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { offset = Z_REFVAL_P(offset); goto isset_again; } else { @@ -17669,7 +17197,7 @@ num_index_prop: if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { /* avoid exception check */ - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); } } else { @@ -17683,7 +17211,7 @@ num_index_prop: } } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -17693,12 +17221,12 @@ num_index_prop: } isset_dim_obj_exit: - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -17708,7 +17236,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -17724,7 +17252,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (IS_CV == IS_CONST) { name = Z_STR_P(offset); } else { name = zval_try_get_tmp_string(offset, &tmp_name); @@ -17736,19 +17264,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (IS_CV != IS_CONST) { zend_tmp_string_release(tmp_name); } isset_object_finish: - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -17759,14 +17287,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_T SAVE_OPLINE(); key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + subject = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { array_key_exists_array: ht = Z_ARRVAL_P(subject); result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); } else { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { subject = Z_REFVAL_P(subject); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { goto array_key_exists_array; @@ -17776,2189 +17304,2463 @@ array_key_exists_array: result = 0; } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; - zend_bool result; - - SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - -try_instanceof: - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; + zval *retval_ptr; + zval *return_value; - if (IS_VAR == IS_CONST) { - ce = CACHED_PTR(opline->extended_value); - if (UNEXPECTED(ce == NULL)) { - ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); - if (EXPECTED(ce)) { - CACHE_PTR(opline->extended_value, ce); - } - } - } else if (IS_VAR == IS_UNUSED) { - ce = zend_fetch_class(NULL, opline->op2.num); - if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + return_value = EX(return_value); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { + SAVE_OPLINE(); + retval_ptr = ZVAL_UNDEFINED_OP1(); + if (return_value) { + ZVAL_NULL(return_value); + } + } else if (!return_value) { + if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); } - result = ce && instanceof_function(Z_OBJCE_P(expr), ce); - } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { - expr = Z_REFVAL_P(expr); - goto try_instanceof; } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { + Z_ADDREF_P(return_value); + } + } + } else if (IS_TMP_VAR == IS_CV) { + do { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { + if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (GC_MAY_LEAK(ref)) { + gc_possible_root(ref); + } + ZVAL_NULL(retval_ptr); + break; + } else { + Z_ADDREF_P(retval_ptr); + } + } else { + retval_ptr = Z_REFVAL_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } + } + ZVAL_COPY_VALUE(return_value, retval_ptr); + } while (0); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + + retval_ptr = Z_REFVAL_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } else { + ZVAL_COPY_VALUE(return_value, retval_ptr); + } } - result = 0; } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varname; - zval *retval; - zend_string *name, *tmp_name; - HashTable *target_symbol_table; + zval *retval_ptr; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - 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); - tmp_name = NULL; - } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - name = zval_try_get_tmp_string(varname, &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } + do { + if ((IS_TMP_VAR & (IS_CONST|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"); - target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); - retval = zend_hash_find_ex(target_symbol_table, name, (IS_TMP_VAR|IS_VAR) == IS_CONST); - if (retval == NULL) { - if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { -fetch_this: - zend_fetch_this_var(type OPLINE_CC EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - if (type == BP_VAR_W) { - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - } else if (type == BP_VAR_IS) { - retval = &EG(uninitialized_zval); - } else { - zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); - if (type == BP_VAR_RW) { - retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (!EX(return_value)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - retval = &EG(uninitialized_zval); + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; + } + + ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } } + break; } - /* 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) { - if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { - goto fetch_this; - } - if (type == BP_VAR_W) { - ZVAL_NULL(retval); - } else if (type == BP_VAR_IS) { - retval = &EG(uninitialized_zval); - } else { - zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); - if (type == BP_VAR_RW) { - ZVAL_NULL(retval); + + retval_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR) { + ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (EX(return_value)) { + ZVAL_NEW_REF(EX(return_value), retval_ptr); } else { - retval = &EG(uninitialized_zval); + } + break; } } - } - if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } + if (EX(return_value)) { + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } + ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } + } while (0); - ZEND_ASSERT(retval != NULL); - if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); - } else { - ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -} + USE_OPLINE + zval *retval; -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -} + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -} + SAVE_OPLINE(); + retval = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - int fetch_type = - (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? - BP_VAR_W : BP_VAR_R; - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(fetch_type ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -} + /* Copy return value into generator->retval */ + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(&generator->retval, retval); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { + Z_ADDREF(generator->retval); + } + } + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_COPY_DEREF(&generator->retval, retval); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_refcounted *ref = Z_COUNTED_P(retval); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -} + retval = Z_REFVAL_P(retval); + ZVAL_COPY_VALUE(&generator->retval, retval); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval)) { + Z_ADDREF_P(retval); + } + } else { + ZVAL_COPY_VALUE(&generator->retval, retval); + } + } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + /* Close the generator to free up resources */ + zend_generator_close(generator, 1); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varname; - zend_string *name, *tmp_name; - HashTable *target_symbol_table; + zval *value, *arg; + uint32_t arg_num = opline->op2.num; - SAVE_OPLINE(); + if (EXPECTED(0)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref: + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} - varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num = opline->op2.num; - 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); - tmp_name = NULL; - } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { - varname = ZVAL_UNDEFINED_OP1(); + if (EXPECTED(1)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; } - name = zval_try_get_tmp_string(varname, &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref: + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); } } + ZEND_VM_NEXT_OPCODE(); +} - target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); - zend_hash_del_ind(target_symbol_table, name); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *arg, *param; - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); + SAVE_OPLINE(); + + if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) { + zend_param_must_be_ref(EX(call)->func, opline->op2.num); } + + arg = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + param = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY(param, arg); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - int result; - zval *varname; - zend_string *name, *tmp_name; - HashTable *target_symbol_table; + zval *expr; + zval *result = EX_VAR(opline->result.var); + HashTable *ht; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(varname); - } else { - name = zval_get_tmp_string(varname, &tmp_name); - } + expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); - value = zend_hash_find_ex(target_symbol_table, name, (IS_TMP_VAR|IS_VAR) == IS_CONST); + switch (opline->extended_value) { + 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: + ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); + if (IS_TMP_VAR & (IS_VAR|IS_CV)) { + ZVAL_DEREF(expr); + } + /* 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_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } - if (!value) { - result = (opline->extended_value & ZEND_ISEMPTY); - } else { - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } - if (!(opline->extended_value & ZEND_ISEMPTY)) { - if (Z_ISREF_P(value)) { - value = Z_REFVAL_P(value); + if (opline->extended_value == IS_ARRAY) { + if (IS_TMP_VAR == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { + if (Z_TYPE_P(expr) != IS_NULL) { + ZVAL_ARR(result, zend_new_array(1)); + expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); + } else { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + } else { + ZVAL_EMPTY_ARRAY(result); + } + } else { + HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST); + if (obj_ht) { + /* fast copy */ + ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht, + (Z_OBJCE_P(expr)->default_properties_count || + Z_OBJ_P(expr)->handlers != &std_object_handlers || + GC_IS_RECURSIVE(obj_ht)))); + zend_release_properties(obj_ht); + } else { + ZVAL_EMPTY_ARRAY(result); + } + } + } else { + ZEND_ASSERT(opline->extended_value == IS_OBJECT); + ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); + if (Z_TYPE_P(expr) == IS_ARRAY) { + ht = zend_symtable_to_proptable(Z_ARR_P(expr)); + if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { + /* TODO: try not to duplicate immutable arrays as well ??? */ + ht = zend_array_dup(ht); + } + Z_OBJ_P(result)->properties = ht; + } else if (Z_TYPE_P(expr) != IS_NULL) { + Z_OBJ_P(result)->properties = ht = zend_new_array(1); + expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); + } else { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + } } - result = Z_TYPE_P(value) > IS_NULL; - } else { - result = !i_zend_is_true(value); - } } - ZEND_VM_SMART_BRANCH(result, 1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; - zend_bool result; + zval *array_ptr, *result; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); -try_instanceof: - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; + array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_TMP_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); + } + Z_FE_POS_P(result) = 0; - if (IS_UNUSED == IS_CONST) { - ce = CACHED_PTR(opline->extended_value); - if (UNEXPECTED(ce == NULL)) { - ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); - if (EXPECTED(ce)) { - CACHE_PTR(opline->extended_value, ce); + ZEND_VM_NEXT_OPCODE(); + } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + + result = EX_VAR(opline->result.var); + ZVAL_OBJ(result, zobj); + if (IS_TMP_VAR != IS_TMP_VAR) { + GC_ADDREF(zobj); + } + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } + } else { + properties = zobj->handlers->get_properties(zobj); } - } else if (IS_UNUSED == IS_UNUSED) { - ce = zend_fetch_class(NULL, opline->op2.num); - if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); } - } else { - ce = Z_CE_P(EX_VAR(opline->op2.var)); } - result = ce && instanceof_function(Z_OBJCE_P(expr), ce); - } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { - expr = Z_REFVAL_P(expr); - goto try_instanceof; } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - result = 0; + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_get_type_by_const(Z_TYPE_P(array_ptr))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; - zend_long count; + zval *array_ptr, *array_ref; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - while (1) { - if (Z_TYPE_P(op1) == IS_ARRAY) { - count = zend_array_count(Z_ARRVAL_P(op1)); - break; - } else if (Z_TYPE_P(op1) == IS_OBJECT) { - zend_object *zobj = Z_OBJ_P(op1); - - /* first, we check if the handler is defined */ - if (zobj->handlers->count_elements) { - if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { - break; - } - if (UNEXPECTED(EG(exception))) { - count = 0; - break; - } - } - /* if not and the object implements Countable we call its count() method */ - if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { - zval retval; - - zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); - count = zval_get_long(&retval); - zval_ptr_dtor(&retval); - break; - } + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + array_ref = array_ptr = NULL; + if (Z_ISREF_P(array_ref)) { + array_ptr = Z_REFVAL_P(array_ref); + } + } else { + array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + } - /* If There's no handler and it doesn't implement Countable then add a warning */ - count = 1; - } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { - op1 = Z_REFVAL_P(op1); - continue; - } else if (Z_TYPE_P(op1) <= IS_NULL) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); } - count = 0; + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); } else { - count = 1; + array_ref = EX_VAR(opline->result.var); + ZVAL_NEW_REF(array_ref, array_ptr); + array_ptr = Z_REFVAL_P(array_ref); } - zend_error(E_WARNING, "%s(): Parameter must be an array or an object that implements Countable", opline->extended_value ? "sizeof" : "count"); - break; - } - - ZVAL_LONG(EX_VAR(opline->result.var), count); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - if (UNEXPECTED(!EX(func)->common.scope)) { - SAVE_OPLINE(); - zend_error(E_WARNING, "get_class() called without object from outside a class"); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + if (IS_TMP_VAR == IS_CONST) { + ZVAL_ARR(array_ptr, zend_array_dup(Z_ARRVAL_P(array_ptr))); } else { - ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); - ZEND_VM_NEXT_OPCODE(); + SEPARATE_ARRAY(array_ptr); } - } else { - zval *op1; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); - SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - while (1) { - if (Z_TYPE_P(op1) == IS_OBJECT) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name); - } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { - op1 = Z_REFVAL_P(op1); - continue; + if (IS_TMP_VAR == IS_VAR) { + + } + ZEND_VM_NEXT_OPCODE(); + } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (Z_OBJ_P(array_ptr)->properties + && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(Z_OBJ_P(array_ptr)->properties); } - zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); - ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); } - break; - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zval *result = EX_VAR(opline->result.var); - ZVAL_COPY(result, value); - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = EX_VAR(opline->op2.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); - if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && - (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { - zend_string *op1_str = Z_STR_P(op1); - zend_string *op2_str = Z_STR_P(op2); - zend_string *str; + if (IS_TMP_VAR == IS_VAR) { - if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if (IS_CV == IS_CONST || IS_CV == IS_CV) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); } else { - ZVAL_STR(EX_VAR(opline->result.var), op2_str); - } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op1_str, 0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } - } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } else { - ZVAL_STR(EX_VAR(opline->result.var), op1_str); - } - if (IS_CV & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op2_str, 0); - } - } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && - !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); - - str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); - memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); - ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if (IS_CV & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op2_str, 0); - } - } else { - str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); - memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); - memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); - ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op1_str, 0); - } - if (IS_CV & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op2_str, 0); + ZEND_VM_NEXT_OPCODE(); } } - ZEND_VM_NEXT_OPCODE(); } else { - SAVE_OPLINE(); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_get_type_by_const(Z_TYPE_P(array_ptr))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + if (IS_TMP_VAR == IS_VAR) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - op1 = ZVAL_UNDEFINED_OP1(); - } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { - op2 = ZVAL_UNDEFINED_OP2(); + } else { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } - concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) { + EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); + } + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; - zval *property; zval *value; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *ref = NULL; + int ret; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_op_object; - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + ref = value; } + value = Z_REFVAL_P(value); + } -assign_op_object: - /* here we are sure we are dealing with an object */ - zobj = Z_OBJ_P(object); - if (IS_CV == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - UNDEF_RESULT(); - break; - } - } - cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - zval *orig_zptr = zptr; - zend_reference *ref; + ret = i_zend_is_true(value); - do { - if (UNEXPECTED(Z_ISREF_P(zptr))) { - ref = Z_REF_P(zptr); - zptr = Z_REFVAL_P(zptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } - if (IS_CV == IS_CONST) { - prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr); - } - if (UNEXPECTED(prop_info)) { - /* special case for typed properties */ - zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_binary_op(zptr, zptr, value OPLINE_CC); - } - } while (0); + if (ret) { + zval *result = EX_VAR(opline->result.var); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } + ZVAL_COPY_VALUE(result, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if (IS_TMP_VAR == IS_VAR && ref) { + zend_reference *r = Z_REF_P(ref); + + if (UNEXPECTED(GC_DELREF(r) == 0)) { + efree_size(r, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); } - } else { - zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); - } - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); } - } while (0); - - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE(); } -/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *value; + zval *ref = NULL; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - do { - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto pre_incdec_object; - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; + if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (IS_TMP_VAR & IS_VAR) { + ref = value; } + value = Z_REFVAL_P(value); + } -pre_incdec_object: - /* here we are sure we are dealing with an object */ - zobj = Z_OBJ_P(object); - if (IS_CV == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - UNDEF_RESULT(); - break; - } - } - cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - if (IS_CV == IS_CONST) { - prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); - } - zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + if (Z_TYPE_P(value) > IS_NULL) { + zval *result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if ((IS_TMP_VAR & IS_VAR) && ref) { + zend_reference *r = Z_REF_P(ref); + + if (UNEXPECTED(GC_DELREF(r) == 0)) { + efree_size(r, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); } - } else { - zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); - } - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); } - } while (0); + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; + zval *value; + zval *result = EX_VAR(opline->result.var); - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - dim = EX_VAR(opline->op2.var); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { -fetch_dim_r_array: - value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R EXECUTE_DATA_CC); - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto fetch_dim_r_array; - } else { - goto fetch_dim_r_slow; + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(result); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_TMP_VAR == IS_CV) { + ZVAL_COPY_DEREF(result, value); + } else if (IS_TMP_VAR == IS_VAR) { + if (UNEXPECTED(Z_ISREF_P(value))) { + ZVAL_COPY_VALUE(result, Z_REFVAL_P(value)); + if (UNEXPECTED(Z_DELREF_P(value) == 0)) { + efree_size(Z_REF_P(value), sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); } } else { -fetch_dim_r_slow: - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(result, value); } } else { - zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(result, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { + Z_ADDREF_P(result); + } + } } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; + zval *op1, *op2; + zend_bool result; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); - + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; - void **cache_slot = NULL; + zval *op1, *op2; + zend_bool result; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = EX_VAR(opline->op2.var); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || - ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - break; - } - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - } - zend_wrong_property_read(offset); - ZVAL_NULL(EX_VAR(opline->result.var)); - goto fetch_obj_r_finish; - } while (0); - } + ZEND_VM_SMART_BRANCH(result, 1); +} - /* here we are sure we are dealing with an object */ - do { - zend_object *zobj = Z_OBJ_P(container); - zend_string *name, *tmp_name; - zval *retval; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif - if (IS_CV == IS_CONST) { - name = Z_STR_P(offset); - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_CONST == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} - if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - retval = OBJ_PROP(zobj, prop_offset); - if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { - goto fetch_obj_r_copy; - } else { -fetch_obj_r_fast_copy: - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); - ZEND_VM_NEXT_OPCODE(); - } - } - } else if (EXPECTED(zobj->properties != NULL)) { - if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { - uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} - if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { - Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var; - if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name))))) { - retval = &p->val; - if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { - goto fetch_obj_r_copy; - } else { - goto fetch_obj_r_fast_copy; - } - } - } - CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); - } - retval = zend_hash_find_ex(zobj->properties, name, 1); - if (EXPECTED(retval)) { - uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; - CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { - goto fetch_obj_r_copy; - } else { - goto fetch_obj_r_fast_copy; - } - } - } + /* op1 and result are the same */ + rope = (zend_string**)EX_VAR(opline->op1.var); + if (IS_CONST == IS_CONST) { + var = RT_CONSTANT(opline, opline->op2); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = RT_CONSTANT(opline, opline->op2); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CONST == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); } } else { - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + SAVE_OPLINE(); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - name = zval_try_get_tmp_string(offset, &tmp_name); - if (UNEXPECTED(!name)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - break; - } + rope[opline->extended_value] = zval_get_string_func(var); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } + } + ZEND_VM_NEXT_OPCODE(); +} - retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var, *ret; + uint32_t i; + size_t len = 0; + char *target; - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); + rope = (zend_string**)EX_VAR(opline->op1.var); + if (IS_CONST == IS_CONST) { + var = RT_CONSTANT(opline, opline->op2); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); } + } else { + var = RT_CONSTANT(opline, opline->op2); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CONST == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); - if (retval != EX_VAR(opline->result.var)) { -fetch_obj_r_copy: - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); - } else if (UNEXPECTED(Z_ISREF_P(retval))) { - zend_unwrap_reference(retval); + if (UNEXPECTED(EG(exception))) { + for (i = 0; i <= opline->extended_value; i++) { + zend_string_release_ex(rope[i], 0); + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } } - } while (0); - -fetch_obj_r_finish: + } + for (i = 0; i <= opline->extended_value; i++) { + len += ZSTR_LEN(rope[i]); + } + ret = EX_VAR(opline->result.var); + ZVAL_STR(ret, zend_string_alloc(len, 0)); + target = Z_STRVAL_P(ret); + for (i = 0; i <= opline->extended_value; i++) { + memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); + target += ZSTR_LEN(rope[i]); + zend_string_release_ex(rope[i], 0); + } + *target = '\0'; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *result; + zval *expr_ptr, new_expr; SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = NULL; + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - result = EX_VAR(opline->result.var); - zend_fetch_property_address( - result, container, (IS_TMP_VAR|IS_VAR), property, IS_CV, - ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), - BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); + } else { + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); - if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_CONST != IS_UNUSED) { + zval *offset = RT_CONSTANT(opline, opline->op2); + zend_string *str; + zend_ulong hval; + +add_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; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_offset(); + zval_ptr_dtor_nogc(expr_ptr); + } + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zval *array; + uint32_t size; USE_OPLINE - zval *property, *container, *result; - - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - result = EX_VAR(opline->result.var); - zend_fetch_property_address(result, container, (IS_TMP_VAR|IS_VAR), property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; - void **cache_slot = NULL; - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || - ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - break; - } - } - ZVAL_NULL(EX_VAR(opline->result.var)); - goto fetch_obj_is_finish; - } while (0); + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - /* here we are sure we are dealing with an object */ - do { - zend_object *zobj = Z_OBJ_P(container); - zend_string *name, *tmp_name; - zval *retval; + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - if (IS_CV == IS_CONST) { - name = Z_STR_P(offset); - cache_slot = CACHE_ADDR(opline->extended_value); + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + if (UNEXPECTED(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)) { + zval *value; - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - retval = OBJ_PROP(zobj, prop_offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { - goto fetch_obj_is_copy; - } else { -fetch_obj_is_fast_copy: - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); - ZEND_VM_NEXT_OPCODE(); - } - } - } else if (EXPECTED(zobj->properties != NULL)) { - if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { - uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { - Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = NULL; - if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name))))) { - retval = &p->val; - if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { - goto fetch_obj_is_copy; - } else { - goto fetch_obj_is_fast_copy; - } - } + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_TMP_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; } - CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, name, 1); - if (EXPECTED(retval)) { - uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; - CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { - goto fetch_obj_is_copy; - } else { - goto fetch_obj_is_fast_copy; - } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); } - } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + } } else { - name = zval_try_get_tmp_string(offset, &tmp_name); - if (UNEXPECTED(!name)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - break; + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } else if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&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); + } - retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); - - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + zval *key = RT_CONSTANT(opline, opline->op2); + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); - if (retval != EX_VAR(opline->result.var)) { -fetch_obj_is_copy: - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); - } else if (UNEXPECTED(Z_ISREF_P(retval))) { - zend_unwrap_reference(retval); + 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); } - } while (0); + } 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); + } -fetch_obj_is_finish: + 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; + } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif + /* 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 (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - /* Behave like FETCH_OBJ_W */ - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *op1; + HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + zval *result; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = RT_CONSTANT((opline+1), (opline+1)->op1); - - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_TMP_VAR == IS_CONST); + } else if (opline->extended_value) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + } else { + result = NULL; + } + } else if (Z_TYPE_P(op1) <= IS_FALSE) { + result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); + } else { + zend_string *key; + zval key_tmp, *val; + + result = NULL; + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { + ZVAL_STR(&key_tmp, key); + if (zend_compare(op1, &key_tmp) == 0) { + result = val; + break; + } + } ZEND_HASH_FOREACH_END(); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} -assign_object: - zobj = Z_OBJ_P(object); - if (IS_CV == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif - if (IS_CONST == IS_CONST) { - orig_type = Z_TYPE_P(value); - } + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var; - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_CONST == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + /* op1 and result are the same */ + rope = (zend_string**)EX_VAR(opline->op1.var); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); } } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var, *ret; + uint32_t i; + size_t len = 0; + char *target; + + rope = (zend_string**)EX_VAR(opline->op1.var); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (UNEXPECTED(EG(exception))) { + for (i = 0; i <= opline->extended_value; i++) { + zend_string_release_ex(rope[i], 0); } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + } + for (i = 0; i <= opline->extended_value; i++) { + len += ZSTR_LEN(rope[i]); + } + ret = EX_VAR(opline->result.var); + ZVAL_STR(ret, zend_string_alloc(len, 0)); + target = Z_STRVAL_P(ret); + for (i = 0; i <= opline->extended_value; i++) { + memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); + target += ZSTR_LEN(rope[i]); + zend_string_release_ex(rope[i], 0); + } + *target = '\0'; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = NULL; + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + } else { + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); } } + } + } - if (!zobj->ce->__set) { + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zend_string *str; + zend_ulong hval; - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); +add_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; } - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_offset(); + zval_ptr_dtor_nogc(expr_ptr); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* 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) { + if (UNEXPECTED(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)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); } - } else if (IS_CONST != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_CONST == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); + } + } else { + zval *value_ptr = NULL; + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_TMP_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; } - } else if (IS_CONST == IS_CV) { - Z_TRY_ADDREF_P(value); } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + } else if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&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); } - goto exit_assign_obj; } } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - ZVAL_DEREF(value); - } + /* Set the new yielded key */ + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if (IS_CV == IS_CONST) { - name = Z_STR_P(property); + 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 { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } - UNDEF_RESULT(); - goto exit_assign_obj; - } + 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; } - value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); - } + /* 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(); -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } + ZEND_VM_RETURN(); +} -exit_assign_obj: +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *op1, *op2; + zend_bool result; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_UNUSED == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } +} -assign_object: - zobj = Z_OBJ_P(object); - if (IS_CV == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; - - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; + if (IS_TMP_VAR == IS_UNUSED) { + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + HANDLE_EXCEPTION(); + } else { +/* prevents "undefined variable opline" errors */ +#if 0 || (IS_TMP_VAR != IS_UNUSED) + zval *retval_ref, *retval_ptr; + zend_arg_info *ret_info = EX(func)->common.arg_info - 1; + retval_ref = retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_CONST) { - orig_type = Z_TYPE_P(value); - } + if (IS_TMP_VAR == IS_CONST) { + ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); + retval_ref = retval_ptr = EX_VAR(opline->result.var); + } else if (IS_TMP_VAR == IS_VAR) { + if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { + retval_ptr = Z_INDIRECT_P(retval_ptr); + } + ZVAL_DEREF(retval_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(retval_ptr); + } - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_TMP_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); + } else { + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); } + retval_ptr = retval_ref; } + } + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), cache_slot, retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +#endif + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = NULL; + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + } else { + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); } } + } + } - if (!zobj->ce->__set) { + if (IS_UNUSED != IS_UNUSED) { + zval *offset = NULL; + zend_string *str; + zend_ulong hval; - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } else if (IS_TMP_VAR != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_TMP_VAR == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else if (IS_TMP_VAR == IS_CV) { - Z_TRY_ADDREF_P(value); - } - } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_UNUSED != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } - goto exit_assign_obj; } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_offset(); + zval_ptr_dtor_nogc(expr_ptr); } - } - - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(value); - } - if (IS_CV == IS_CONST) { - name = Z_STR_P(property); } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); } } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -assign_object: - zobj = Z_OBJ_P(object); - if (IS_CV == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + if (UNEXPECTED(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)) { + zval *value; - if (IS_VAR == IS_CONST) { - orig_type = Z_TYPE_P(value); - } + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = NULL; - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_TMP_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); } - goto exit_assign_obj; - } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + } } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; - } - } - - if (!zobj->ce->__set) { + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } else if (IS_VAR != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_VAR == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else if (IS_VAR == IS_CV) { - Z_TRY_ADDREF_P(value); - } + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + } else if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&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); } - goto exit_assign_obj; } } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(value); + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + zval *key = NULL; + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, 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 (IS_CV == IS_CONST) { - name = Z_STR_P(property); + 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 { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; - } + generator->send_target = NULL; } - value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); - } + /* 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(); -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_string *type; + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + type = zend_zval_get_type(op1); + if (EXPECTED(type)) { + ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); + } else { + ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; +#endif - SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_CV == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto assign_object; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } +} -assign_object: - zobj = Z_OBJ_P(object); - if (IS_CV == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { - void **cache_slot = CACHE_ADDR(opline->extended_value); - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property_val; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var; - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + /* op1 and result are the same */ + rope = (zend_string**)EX_VAR(opline->op1.var); + if (IS_CV == IS_CONST) { + var = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CV == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} - if (IS_CV == IS_CONST) { - orig_type = Z_TYPE_P(value); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var, *ret; + uint32_t i; + size_t len = 0; + char *target; - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + rope = (zend_string**)EX_VAR(opline->op1.var); + if (IS_CV == IS_CONST) { + var = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CV == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); - /* will remain valid, thus no need to check prop_info in future here */ - if (IS_CV == IS_CONST && Z_TYPE_P(value) == orig_type) { - CACHE_PTR_EX(cache_slot + 2, NULL); - } - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + if (UNEXPECTED(EG(exception))) { + for (i = 0; i <= opline->extended_value; i++) { + zend_string_release_ex(rope[i], 0); } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } + } + } + for (i = 0; i <= opline->extended_value; i++) { + len += ZSTR_LEN(rope[i]); + } + ret = EX_VAR(opline->result.var); + ZVAL_STR(ret, zend_string_alloc(len, 0)); + target = Z_STRVAL_P(ret); + for (i = 0; i <= opline->extended_value; i++) { + memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); + target += ZSTR_LEN(rope[i]); + zend_string_release_ex(rope[i], 0); + } + *target = '\0'; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = NULL; + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); - if (property_val) { - goto fast_assign_obj; + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + } else { + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); } } + } + } - if (!zobj->ce->__set) { + if (IS_CV != IS_UNUSED) { + zval *offset = EX_VAR(opline->op2.var); + zend_string *str; + zend_ulong hval; - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } else if (IS_CV != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (IS_CV == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (GC_DELREF(ref) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else { - value = Z_REFVAL_P(value); - Z_TRY_ADDREF_P(value); - } - } else if (IS_CV == IS_CV) { - Z_TRY_ADDREF_P(value); - } - } - zend_hash_add_new(zobj->properties, Z_STR_P(property), value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); +add_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; } - goto exit_assign_obj; } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_offset(); + zval_ptr_dtor_nogc(expr_ptr); } - } - - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(value); - } - if (IS_CV == IS_CONST) { - name = Z_STR_P(property); } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - - UNDEF_RESULT(); - goto exit_assign_obj; + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); } } - - value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - -exit_assign_obj: - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zval *array; + uint32_t size; USE_OPLINE - zval *property, *container, *value_ptr; - - SAVE_OPLINE(); - - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (1) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - if (IS_CV == IS_CONST) { - zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } - } else { - if (IS_CV == IS_CONST) { - zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - zend_assign_to_property_reference(container, (IS_TMP_VAR|IS_VAR), property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; - ZEND_VM_NEXT_OPCODE_EX(1, 2); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - if (1) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - if (IS_CV == IS_CONST) { - zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + if (UNEXPECTED(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)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } } else { - zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + zval *value_ptr = NULL; + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_TMP_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + } } else { - if (IS_CV == IS_CONST) { - zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } else if (IS_TMP_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { - zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } } } } else { - zend_assign_to_property_reference(container, (IS_TMP_VAR|IS_VAR), property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, 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); + } - ZEND_VM_NEXT_OPCODE_EX(1, 2); -} + 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; + } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - zend_string *op1_str, *op2_str, *str; + /* 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(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = EX_VAR(opline->op2.var); - if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && - (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { - zend_string *op1_str = Z_STR_P(op1); - zend_string *op2_str = Z_STR_P(op2); - zend_string *str; + ZEND_VM_RETURN(); +} - if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if (IS_CV == IS_CONST || IS_CV == IS_CV) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); - } else { - ZVAL_STR(EX_VAR(opline->result.var), op2_str); - } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op1_str, 0); - } - } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); - } else { - ZVAL_STR(EX_VAR(opline->result.var), op1_str); - } - if (IS_CV & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op2_str, 0); - } - } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && - !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *closure, *var; - str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); - memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); - ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if (IS_CV & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op2_str, 0); - } + closure = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (opline->extended_value & ZEND_BIND_REF) { + /* By-ref binding */ + var = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); + if (Z_ISREF_P(var)) { + Z_ADDREF_P(var); } else { - str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); - memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); - memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); - ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op1_str, 0); - } - if (IS_CV & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op2_str, 0); - } - } - ZEND_VM_NEXT_OPCODE(); - } - - SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - op1_str = Z_STR_P(op1); - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - op1_str = zend_string_copy(Z_STR_P(op1)); - } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + ZVAL_MAKE_REF_EX(var, 2); } - op1_str = zval_get_string_func(op1); - } - if (IS_CV == IS_CONST) { - op2_str = Z_STR_P(op2); - } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - op2_str = zend_string_copy(Z_STR_P(op2)); } else { - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - } - op2_str = zval_get_string_func(op2); - } - do { - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { - GC_ADDREF(op2_str); - } - } - ZVAL_STR(EX_VAR(opline->result.var), op2_str); - zend_string_release_ex(op1_str, 0); - break; - } - } - if (IS_CV != IS_CONST) { - if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { - GC_ADDREF(op1_str); - } - } - ZVAL_STR(EX_VAR(opline->result.var), op1_str); - zend_string_release_ex(op2_str, 0); - break; + var = EX_VAR(opline->op2.var); + if (UNEXPECTED(Z_ISUNDEF_P(var)) && !(opline->extended_value & ZEND_BIND_IMPLICIT)) { + SAVE_OPLINE(); + var = ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); } } - str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); - memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); - memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); - ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_string_release_ex(op1_str, 0); - } - if (IS_CV != IS_CONST) { - zend_string_release_ex(op2_str, 0); - } - } while (0); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_DEREF(var); + Z_TRY_ADDREF_P(var); + } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zend_closure_bind_var_ex(closure, + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)), var); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; - zend_execute_data *call; - uint32_t call_info; - - SAVE_OPLINE(); - - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV != IS_CONST) { - function_name = EX_VAR(opline->op2.var); - } + zval *var_ptr; - if (IS_CV != IS_CONST && - UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - do { - if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { - function_name = Z_REFVAL_P(function_name); - if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { - break; - } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - } - zend_throw_error(NULL, "Method name must be a string"); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } while (0); + SAVE_OPLINE(); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_NULL(var_ptr); + ZVAL_UNDEFINED_OP1(); } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - do { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - object = ZVAL_UNDEFINED_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { - if (IS_CV != IS_CONST) { - - } - HANDLE_EXCEPTION(); - } - } - if (IS_CV == IS_CONST) { - function_name = EX_VAR(opline->op2.var); - } - zend_invalid_method_call(object, function_name); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); + break; } - } while (0); - } - - obj = Z_OBJ_P(object); - called_scope = obj->ce; - - if (IS_CV == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); - } else { - zend_object *orig_obj = obj; - - if (IS_CV == IS_CONST) { - function_name = EX_VAR(opline->op2.var); } + increment_function(var_ptr); + } while (0); - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); - if (UNEXPECTED(fbc == NULL)) { - if (EXPECTED(!EG(exception))) { - zend_undefined_method(obj->ce, Z_STR_P(function_name)); - } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - if (IS_CV == IS_CONST && - EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && - EXPECTED(obj == orig_obj)) { - CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); - } - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; - } - if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { - init_func_run_time_cache(&fbc->op_array); - } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (IS_CV != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - } +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - /* call static method */ - obj = (zend_object*)called_scope; - call_info = ZEND_CALL_NESTED_FUNCTION; - } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV) { - GC_ADDREF(obj); /* For $this pointer */ - } else { - zval *free_op1 = EX_VAR(opline->op1.var); - if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - zval_ptr_dtor_nogc(free_op1); - } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_increment_function(var_ptr); + if (UNEXPECTED(0)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); } - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + ZEND_VM_NEXT_OPCODE(); } - call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, obj); - call->prev_execute_data = EX(call); - EX(call) = call; - - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - double d1, d2; + zval *var_ptr; - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = EX_VAR(opline->op2.var); - if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { -case_true: - ZEND_VM_SMART_BRANCH_TRUE(); - } else { -case_false: - ZEND_VM_SMART_BRANCH_FALSE(); - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = (double)Z_LVAL_P(op1); - d2 = Z_DVAL_P(op2); - goto case_double; - } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = Z_DVAL_P(op1); - d2 = Z_DVAL_P(op2); -case_double: - if (d1 == d2) { - goto case_true; - } else { - goto case_false; - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - d1 = Z_DVAL_P(op1); - d2 = (double)Z_LVAL_P(op2); - goto case_double; - } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (result) { - goto case_true; - } else { - goto case_false; - } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_increment_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); } + ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + + ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - int result; - zend_ulong hval; - zval *offset; + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = EX_VAR(opline->op2.var); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_NULL(var_ptr); + ZVAL_UNDEFINED_OP1(); + } - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; - zval *value; - zend_string *str; + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); -isset_dim_obj_array: - ht = Z_ARRVAL_P(container); -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; - } - } - value = zend_hash_find_ex_ind(ht, str, IS_CV == IS_CONST); - } 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 if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { - offset = Z_REFVAL_P(offset); - goto isset_again; - } else { - value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); - if (UNEXPECTED(EG(exception))) { - result = 0; - goto isset_dim_obj_exit; + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); + break; } } + decrement_function(var_ptr); + } while (0); - if (!(opline->extended_value & ZEND_ISEMPTY)) { - /* > 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); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } - if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { - /* avoid exception check */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - ZEND_VM_SMART_BRANCH(result, 0); - } - } else { - result = (value == NULL || !i_zend_is_true(value)); - } - goto isset_dim_obj_exit; - } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto isset_dim_obj_array; +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(0)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); } + ZEND_VM_NEXT_OPCODE(); } - if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { - offset++; - } - if (!(opline->extended_value & ZEND_ISEMPTY)) { - result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); - } else { - result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); - } + ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} -isset_dim_obj_exit: +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - int result; - zval *offset; - zend_string *name, *tmp_name; + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_NULL(var_ptr); + ZVAL_UNDEFINED_OP1(); + } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || - ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { - result = (opline->extended_value & ZEND_ISEMPTY); - goto isset_object_finish; + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); + break; } - } else { - result = (opline->extended_value & ZEND_ISEMPTY); - goto isset_object_finish; } - } + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - if (IS_CV == IS_CONST) { - name = Z_STR_P(offset); - } else { - name = zval_try_get_tmp_string(offset, &tmp_name); - if (UNEXPECTED(!name)) { - result = 0; - goto isset_object_finish; - } - } + increment_function(var_ptr); + } while (0); - result = - (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); - } +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; -isset_object_finish: + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + fast_long_increment_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *var_ptr; - zval *key, *subject; - HashTable *ht; - zend_bool result; + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_NULL(var_ptr); + ZVAL_UNDEFINED_OP1(); + } - key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - subject = EX_VAR(opline->op2.var); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); - if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { -array_key_exists_array: - ht = Z_ARRVAL_P(subject); - result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); - } else { - if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { - subject = Z_REFVAL_P(subject); - if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { - goto array_key_exists_array; + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); + break; } } - zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); - result = 0; - } + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + + decrement_function(var_ptr); + } while (0); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + fast_long_decrement_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; zval *return_value; - retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); - if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } } else if (!return_value) { - if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { + if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); - if (IS_TMP_VAR == IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { Z_ADDREF_P(return_value); } } - } else if (IS_TMP_VAR == IS_CV) { + } else if (IS_VAR == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { @@ -19982,7 +19784,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA } ZVAL_COPY_VALUE(return_value, retval_ptr); } while (0); - } else /* if (IS_TMP_VAR == IS_VAR) */ { + } else /* if (IS_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); @@ -20001,159 +19803,394 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + + SAVE_OPLINE(); + + do { + if ((IS_VAR & (IS_CONST|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_CC); + if (!EX(return_value)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; + } + + ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (IS_VAR == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } + } + break; + } + + retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR) { + ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (EX(return_value)) { + ZVAL_NEW_REF(EX(return_value), retval_ptr); + } else { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + break; + } + } + + if (EX(return_value)) { + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } + ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } while (0); + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval; + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + retval = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* Copy return value into generator->retval */ + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(&generator->retval, retval); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { + Z_ADDREF(generator->retval); + } + } + } else if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(&generator->retval, retval); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_refcounted *ref = Z_COUNTED_P(retval); + + retval = Z_REFVAL_P(retval); + ZVAL_COPY_VALUE(&generator->retval, retval); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval)) { + Z_ADDREF_P(retval); + } + } else { + ZVAL_COPY_VALUE(&generator->retval, retval); + } + } + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + +static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr))) { + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; + + if (EXPECTED(0)) { + if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } else { + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *retval_ptr; - - SAVE_OPLINE(); + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; - do { - if ((IS_TMP_VAR & (IS_CONST|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"); + if (EXPECTED(1)) { + if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } - retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (!EX(return_value)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } else { - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - break; - } + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY_VALUE(arg, varptr); - ZVAL_NEW_REF(EX(return_value), retval_ptr); - if (IS_TMP_VAR == IS_CONST) { - Z_TRY_ADDREF_P(retval_ptr); - } - } - break; + if (EXPECTED(Z_ISREF_P(varptr) || + QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } else { + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - retval_ptr = NULL; - - if (IS_TMP_VAR == IS_VAR) { - ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { - zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - } else { + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY_VALUE(arg, varptr); - } - break; - } + if (EXPECTED(Z_ISREF_P(varptr) || + ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); } + } - if (EX(return_value)) { - if (Z_ISREF_P(retval_ptr)) { - Z_ADDREF_P(retval_ptr); - } else { - ZVAL_MAKE_REF_EX(retval_ptr, 2); - } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); - } + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - } while (0); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; - ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + SAVE_OPLINE(); + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *retval; + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + if (EXPECTED(0)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } - SAVE_OPLINE(); - retval = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } - /* Copy return value into generator->retval */ - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { - ZVAL_COPY_VALUE(&generator->retval, retval); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { - Z_ADDREF(generator->retval); - } - } - } else if (IS_TMP_VAR == IS_CV) { - ZVAL_COPY_DEREF(&generator->retval, retval); - } else /* if (IS_TMP_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(retval))) { - zend_refcounted *ref = Z_COUNTED_P(retval); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); - retval = Z_REFVAL_P(retval); - ZVAL_COPY_VALUE(&generator->retval, retval); + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); if (UNEXPECTED(GC_DELREF(ref) == 0)) { efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(retval)) { - Z_ADDREF_P(retval); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); } } else { - ZVAL_COPY_VALUE(&generator->retval, retval); + ZVAL_COPY_VALUE(arg, varptr); } } - /* Close the generator to free up resources */ - zend_generator_close(generator, 1); - - /* Pass execution back to handling code */ - ZEND_VM_RETURN(); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value, *arg; + zval *varptr, *arg; uint32_t arg_num = opline->op2.num; - if (EXPECTED(0)) { - if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_val_by_ref; + if (EXPECTED(1)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; } - } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); } } + ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value, *arg; - uint32_t arg_num = opline->op2.num; + zval *varptr, *arg; - if (EXPECTED(1)) { - if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_val_by_ref; - } - } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { Z_ADDREF_P(arg); } + } else { + ZVAL_COPY_VALUE(arg, varptr); } + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *arg, *param; @@ -20164,14 +20201,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEN zend_param_must_be_ref(EX(call)->func, opline->op2.num); } - arg = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + arg = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); param = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY(param, arg); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -20179,7 +20216,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC HashTable *ht; SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); switch (opline->extended_value) { case IS_LONG: @@ -20193,27 +20230,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC break; default: ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); - if (IS_TMP_VAR & (IS_VAR|IS_CV)) { + if (IS_VAR & (IS_VAR|IS_CV)) { ZVAL_DEREF(expr); } /* 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 (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_TMP_VAR != IS_TMP_VAR) { + } else if (IS_VAR != IS_TMP_VAR) { if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } if (opline->extended_value == IS_ARRAY) { - if (IS_TMP_VAR == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { + if (IS_VAR == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { if (Z_TYPE_P(expr) != IS_NULL) { ZVAL_ARR(result, zend_new_array(1)); expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); - if (IS_TMP_VAR == IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); @@ -20247,7 +20285,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC } else if (Z_TYPE_P(expr) != IS_NULL) { Z_OBJ_P(result)->properties = ht = zend_new_array(1); expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); - if (IS_TMP_VAR == IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); @@ -20260,31 +20298,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *result; SAVE_OPLINE(); - array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + array_ptr = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); - if (IS_TMP_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + if (IS_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { Z_ADDREF_P(array_ptr); } Z_FE_POS_P(result) = 0; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); - } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { zend_object *zobj = Z_OBJ_P(array_ptr); if (!zobj->ce->get_iterator) { HashTable *properties; result = EX_VAR(opline->result.var); ZVAL_OBJ(result, zobj); - if (IS_TMP_VAR != IS_TMP_VAR) { + if (IS_VAR != IS_TMP_VAR) { GC_ADDREF(zobj); } properties = zobj->properties; @@ -20300,6 +20339,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE } Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); @@ -20322,110 +20362,432 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *array_ref; SAVE_OPLINE(); - if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { - array_ref = array_ptr = NULL; + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(array_ref)) { array_ptr = Z_REFVAL_P(array_ref); } } else { - array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + } + + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ref = EX_VAR(opline->result.var); + ZVAL_NEW_REF(array_ref, array_ptr); + array_ptr = Z_REFVAL_P(array_ref); + } + if (IS_VAR == IS_CONST) { + ZVAL_ARR(array_ptr, zend_array_dup(Z_ARRVAL_P(array_ptr))); + } else { + SEPARATE_ARRAY(array_ptr); + } + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); + + if (IS_VAR == IS_VAR) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + ZEND_VM_NEXT_OPCODE(); + } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (Z_OBJ_P(array_ptr)->properties + && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(Z_OBJ_P(array_ptr)->properties); + } + Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_get_type_by_const(Z_TYPE_P(array_ptr))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + if (IS_VAR == IS_VAR) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array; + zval *value; + uint32_t value_type; + HashTable *fe_ht; + HashPosition pos; + Bucket *p; + + array = EX_VAR(opline->op1.var); + SAVE_OPLINE(); + if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { + fe_ht = Z_ARRVAL_P(array); + pos = Z_FE_POS_P(array); + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ +fe_fetch_r_exit: + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF)) { + if (UNEXPECTED(value_type == IS_INDIRECT)) { + value = Z_INDIRECT_P(value); + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + } else { + break; + } + } + pos++; + p++; + } + Z_FE_POS_P(array) = pos + 1; + if (RETURN_VALUE_USED(opline)) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } + } + } else { + zend_object_iterator *iter; + + ZEND_ASSERT(Z_TYPE_P(array) == IS_OBJECT); + if ((iter = zend_iterator_unwrap(array)) == NULL) { + /* plain object */ + + fe_ht = Z_OBJPROP_P(array); + pos = zend_hash_iterator_pos(Z_FE_ITER_P(array), fe_ht); + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_r_exit; + } + + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF)) { + if (UNEXPECTED(value_type == IS_INDIRECT)) { + value = Z_INDIRECT_P(value); + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF) + && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) { + break; + } + } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0) + || !p->key + || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) { + break; + } + } + pos++; + p++; + } + if (RETURN_VALUE_USED(opline)) { + if (UNEXPECTED(!p->key)) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else if (ZSTR_VAL(p->key)[0]) { + ZVAL_STR_COPY(EX_VAR(opline->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->result.var), prop_name, prop_name_len); + } + } + EG(ht_iterators)[Z_FE_ITER_P(array)].pos = pos + 1; + } else { + if (EXPECTED(++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); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(iter->funcs->valid(iter) == FAILURE)) { + /* reached end of iteration */ + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + goto fe_fetch_r_exit; + } + } + value = iter->funcs->get_current_data(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (!value) { + /* failure in get_current_data */ + goto fe_fetch_r_exit; + } + if (RETURN_VALUE_USED(opline)) { + if (iter->funcs->get_current_key) { + iter->funcs->get_current_key(iter, EX_VAR(opline->result.var)); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } else { + ZVAL_LONG(EX_VAR(opline->result.var), iter->index); + } + } + value_type = Z_TYPE_INFO_P(value); + } + } + + if (EXPECTED(opline->op2_type == IS_CV)) { + zval *variable_ptr = EX_VAR(opline->op2.var); + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zval *res = EX_VAR(opline->op2.var); + zend_refcounted *gc = Z_COUNTED_P(value); + + ZVAL_COPY_VALUE_EX(res, value, gc, value_type); + if (Z_TYPE_INFO_REFCOUNTED(value_type)) { + GC_ADDREF(gc); + } } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array; + zval *value; + uint32_t value_type; + HashTable *fe_ht; + HashPosition pos; + Bucket *p; - if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { - if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { - if (array_ptr == array_ref) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); + array = EX_VAR(opline->op1.var); + SAVE_OPLINE(); + + ZVAL_DEREF(array); + if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { + pos = zend_hash_iterator_pos_ex(Z_FE_ITER_P(EX_VAR(opline->op1.var)), array); + fe_ht = Z_ARRVAL_P(array); + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_w_exit; } - Z_ADDREF_P(array_ref); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - } else { - array_ref = EX_VAR(opline->result.var); - ZVAL_NEW_REF(array_ref, array_ptr); - array_ptr = Z_REFVAL_P(array_ref); + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF)) { + if (UNEXPECTED(value_type == IS_INDIRECT)) { + value = Z_INDIRECT_P(value); + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + } else { + break; + } + } + pos++; + p++; } - if (IS_TMP_VAR == IS_CONST) { - ZVAL_ARR(array_ptr, zend_array_dup(Z_ARRVAL_P(array_ptr))); - } else { - SEPARATE_ARRAY(array_ptr); + if (RETURN_VALUE_USED(opline)) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; + } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { + zend_object_iterator *iter; - if (IS_TMP_VAR == IS_VAR) { + if ((iter = zend_iterator_unwrap(array)) == NULL) { + /* plain object */ - } - ZEND_VM_NEXT_OPCODE(); - } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { - if (array_ptr == array_ref) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); + fe_ht = Z_OBJPROP_P(array); + pos = zend_hash_iterator_pos(Z_FE_ITER_P(EX_VAR(opline->op1.var)), fe_ht); + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_w_exit; } - Z_ADDREF_P(array_ref); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - } else { - array_ptr = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(array_ptr, array_ref); + + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF)) { + if (UNEXPECTED(value_type == IS_INDIRECT)) { + value = Z_INDIRECT_P(value); + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF) + && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) { + if ((value_type & Z_TYPE_MASK) != IS_REFERENCE) { + zend_property_info *prop_info = + zend_get_typed_property_info_for_slot(Z_OBJ_P(array), value); + if (UNEXPECTED(prop_info)) { + ZVAL_NEW_REF(value, value); + ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(value), prop_info); + value_type = IS_REFERENCE_EX; + } + } + break; + } + } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0) + || !p->key + || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) { + break; + } + } + pos++; + p++; } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + if (RETURN_VALUE_USED(opline)) { + if (UNEXPECTED(!p->key)) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else if (ZSTR_VAL(p->key)[0]) { + ZVAL_STR_COPY(EX_VAR(opline->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->result.var), prop_name, prop_name_len); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; } else { - zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); - - if (IS_TMP_VAR == IS_VAR) { - - } else { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (++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); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(iter->funcs->valid(iter) == FAILURE)) { + /* reached end of iteration */ + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + goto fe_fetch_w_exit; + } } - if (UNEXPECTED(EG(exception))) { + value = iter->funcs->get_current_data(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); HANDLE_EXCEPTION(); - } else if (is_empty) { - ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); - } else { - ZEND_VM_NEXT_OPCODE(); } + if (!value) { + /* failure in get_current_data */ + goto fe_fetch_w_exit; + } + if (RETURN_VALUE_USED(opline)) { + if (iter->funcs->get_current_key) { + iter->funcs->get_current_key(iter, EX_VAR(opline->result.var)); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } else { + ZVAL_LONG(EX_VAR(opline->result.var), iter->index); + } + } + value_type = Z_TYPE_INFO_P(value); } } else { - zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_get_type_by_const(Z_TYPE_P(array_ptr))); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - if (IS_TMP_VAR == IS_VAR) { - - } else { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_get_type_by_const(Z_TYPE_P(array))); + if (UNEXPECTED(EG(exception))) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); } - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); +fe_fetch_w_exit: + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); } -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (EXPECTED((value_type & Z_TYPE_MASK) != IS_REFERENCE)) { + zend_refcounted *gc = Z_COUNTED_P(value); + zval *ref; + ZVAL_NEW_EMPTY_REF(value); + ref = Z_REFVAL_P(value); + ZVAL_COPY_VALUE_EX(ref, value, gc, value_type); + } + if (EXPECTED(opline->op2_type == IS_CV)) { + zval *variable_ptr = EX_VAR(opline->op2.var); + if (EXPECTED(variable_ptr != value)) { + zend_reference *ref; - if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) - && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) { - EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); + ref = Z_REF_P(value); + GC_ADDREF(ref); + i_zval_ptr_dtor(variable_ptr); + ZVAL_REF(variable_ptr, ref); + } + } else { + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->op2.var), Z_REF_P(value)); } - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -20433,10 +20795,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_ int ret; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) { - if (IS_TMP_VAR == IS_VAR) { + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { ref = value; } value = Z_REFVAL_P(value); @@ -20454,11 +20816,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_ zval *result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, value); - if (IS_TMP_VAR == IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_TMP_VAR == IS_CV) { + } else if (IS_VAR == IS_CV) { if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if (IS_TMP_VAR == IS_VAR && ref) { + } else if (IS_VAR == IS_VAR && ref) { zend_reference *r = Z_REF_P(ref); if (UNEXPECTED(GC_DELREF(r) == 0)) { @@ -20474,17 +20836,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; zval *ref = NULL; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - if (IS_TMP_VAR & IS_VAR) { + if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (IS_VAR & IS_VAR) { ref = value; } value = Z_REFVAL_P(value); @@ -20493,11 +20855,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND if (Z_TYPE_P(value) > IS_NULL) { zval *result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, value); - if (IS_TMP_VAR == IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_TMP_VAR == IS_CV) { + } else if (IS_VAR == IS_CV) { if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if ((IS_TMP_VAR & IS_VAR) && ref) { + } else if ((IS_VAR & IS_VAR) && ref) { zend_reference *r = Z_REF_P(ref); if (UNEXPECTED(GC_DELREF(r) == 0)) { @@ -20513,23 +20875,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; zval *result = EX_VAR(opline->result.var); - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { SAVE_OPLINE(); ZVAL_UNDEFINED_OP1(); ZVAL_NULL(result); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } - if (IS_TMP_VAR == IS_CV) { + if (IS_VAR == IS_CV) { ZVAL_COPY_DEREF(result, value); - } else if (IS_TMP_VAR == IS_VAR) { + } else if (IS_VAR == IS_VAR) { if (UNEXPECTED(Z_ISREF_P(value))) { ZVAL_COPY_VALUE(result, Z_REFVAL_P(value)); if (UNEXPECTED(Z_DELREF_P(value) == 0)) { @@ -20542,7 +20904,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP } } else { ZVAL_COPY_VALUE(result, value); - if (IS_TMP_VAR == IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { Z_ADDREF_P(result); } @@ -20551,3289 +20913,3427 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - op2 = RT_CONSTANT(opline, opline->op2); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_SMART_BRANCH(result, 1); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - op2 = RT_CONSTANT(opline, opline->op2); - result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_SMART_BRANCH(result, 1); -} + zval *varptr, *arg; -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - if (IS_CONST == IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + if (IS_VAR == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_string **rope; - zval *var; - - /* op1 and result are the same */ - rope = (zend_string**)EX_VAR(opline->op1.var); - if (IS_CONST == IS_CONST) { - var = RT_CONSTANT(opline, opline->op2); - rope[opline->extended_value] = Z_STR_P(var); - if (UNEXPECTED(Z_REFCOUNTED_P(var))) { - Z_ADDREF_P(var); - } - } else { - var = RT_CONSTANT(opline, opline->op2); - if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { - if (IS_CONST == IS_CV) { - rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); - } else { - rope[opline->extended_value] = Z_STR_P(var); - } - } else { - SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - } - rope[opline->extended_value] = zval_get_string_func(var); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - } ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; - zval *var, *ret; - uint32_t i; - size_t len = 0; - char *target; - - rope = (zend_string**)EX_VAR(opline->op1.var); - if (IS_CONST == IS_CONST) { - var = RT_CONSTANT(opline, opline->op2); - rope[opline->extended_value] = Z_STR_P(var); - if (UNEXPECTED(Z_REFCOUNTED_P(var))) { - Z_ADDREF_P(var); - } - } else { - var = RT_CONSTANT(opline, opline->op2); - if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { - if (IS_CONST == IS_CV) { - rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); - } else { - rope[opline->extended_value] = Z_STR_P(var); - } - } else { - SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - } - rope[opline->extended_value] = zval_get_string_func(var); + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; - if (UNEXPECTED(EG(exception))) { - for (i = 0; i <= opline->extended_value; i++) { - zend_string_release_ex(rope[i], 0); - } - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } - } - for (i = 0; i <= opline->extended_value; i++) { - len += ZSTR_LEN(rope[i]); + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - ret = EX_VAR(opline->result.var); - ZVAL_STR(ret, zend_string_alloc(len, 0)); - target = Z_STRVAL_P(ret); - for (i = 0; i <= opline->extended_value; i++) { - memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); - target += ZSTR_LEN(rope[i]); - zend_string_release_ex(rope[i], 0); + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_VAR == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); } - *target = '\0'; ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; + zval *op1, *op2; + zend_bool result; SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = NULL; - if (Z_ISREF_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } else { - ZVAL_MAKE_REF_EX(expr_ptr, 2); - } - - } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_TMP_VAR) { - /* pass */ - } else if (IS_TMP_VAR == IS_CONST) { - Z_TRY_ADDREF_P(expr_ptr); - } else if (IS_TMP_VAR == IS_CV) { - ZVAL_DEREF(expr_ptr); - Z_TRY_ADDREF_P(expr_ptr); - } else /* if (IS_TMP_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { - zend_refcounted *ref = Z_COUNTED_P(expr_ptr); - - expr_ptr = Z_REFVAL_P(expr_ptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } - } - } - } - - if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); - zend_string *str; - zend_ulong hval; - -add_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; - } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { - offset = Z_REFVAL_P(offset); - goto add_again; - } else if (Z_TYPE_P(offset) == IS_NULL) { - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else if (Z_TYPE_P(offset) == IS_DOUBLE) { - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - } else if (Z_TYPE_P(offset) == IS_FALSE) { - hval = 0; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_TRUE) { - hval = 1; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_RESOURCE) { - zend_use_resource_as_offset(offset); - hval = Z_RES_HANDLE_P(offset); - goto num_index; - } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { - ZVAL_UNDEFINED_OP2(); - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else { - zend_illegal_offset(); - zval_ptr_dtor_nogc(expr_ptr); - } + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { - zend_cannot_add_element(); - zval_ptr_dtor_nogc(expr_ptr); - } - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE + zval *op1, *op2; + zend_bool result; - array = EX_VAR(opline->result.var); - if (IS_TMP_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - ZVAL_ARR(array, zend_new_array(size)); - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init_mixed(Z_ARRVAL_P(array)); - } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); - } + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *object; + zval *property; + zval *value; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); - /* Set the new yielded value */ - if (IS_TMP_VAR != IS_UNUSED) { - if (UNEXPECTED(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)) { - zval *value; + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - zval *value_ptr = NULL; + zval *orig_zptr = zptr; + zend_reference *ref; - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ do { - if (IS_TMP_VAR == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); break; } } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); + + if (IS_CONST == IS_CONST) { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr); + } + if (UNEXPECTED(prop_info)) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); - } - } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&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 (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); } } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { - key = Z_REFVAL_P(key); - } - ZVAL_COPY(&generator->key, 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); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } - } 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(); + } while (0); - /* 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(); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - ZEND_VM_RETURN(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; - HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); - zval *result; + zval *var_ptr; + zval *value, *container, *dim; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_TMP_VAR == IS_CONST); - } else if (opline->extended_value) { - if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { - result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); +assign_dim_op_new_array: + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; + } } else { - result = NULL; + if (IS_CONST == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } } - } else if (Z_TYPE_P(op1) <= IS_FALSE) { - result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { - zend_string *key; - zval key_tmp, *val; + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; + } + } - result = NULL; - ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { - ZVAL_STR(&key_tmp, key); - if (zend_compare(op1, &key_tmp) == 0) { - result = val; - break; + dim = RT_CONSTANT(opline, opline->op2); + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; } - } ZEND_HASH_FOREACH_END(); + zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ZVAL_ARR(container, zend_new_array(8)); + goto assign_dim_op_new_array; + } else { + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 USE_OPLINE -#endif + zval *var_ptr; + zval *value; - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; - zval *var; + zval *object; + zval *property; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; - /* op1 and result are the same */ - rope = (zend_string**)EX_VAR(opline->op1.var); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - rope[opline->extended_value] = Z_STR_P(var); - if (UNEXPECTED(Z_REFCOUNTED_P(var))) { - Z_ADDREF_P(var); - } - } else { - var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV) { - rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); - } else { - rope[opline->extended_value] = Z_STR_P(var); + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; } - } else { - SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - rope[opline->extended_value] = zval_get_string_func(var); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } - } - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_string **rope; - zval *var, *ret; - uint32_t i; - size_t len = 0; - char *target; - rope = (zend_string**)EX_VAR(opline->op1.var); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - rope[opline->extended_value] = Z_STR_P(var); - if (UNEXPECTED(Z_REFCOUNTED_P(var))) { - Z_ADDREF_P(var); - } - } else { - var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV) { - rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); - } else { - rope[opline->extended_value] = Z_STR_P(var); - } +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); } else { - SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; } - rope[opline->extended_value] = zval_get_string_func(var); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if (UNEXPECTED(EG(exception))) { - for (i = 0; i <= opline->extended_value; i++) { - zend_string_release_ex(rope[i], 0); + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); + } else { + if (IS_CONST == IS_CONST) { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + } else { + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); + } + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); } - } - for (i = 0; i <= opline->extended_value; i++) { - len += ZSTR_LEN(rope[i]); - } - ret = EX_VAR(opline->result.var); - ZVAL_STR(ret, zend_string_alloc(len, 0)); - target = Z_STRVAL_P(ret); - for (i = 0; i <= opline->extended_value; i++) { - memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); - target += ZSTR_LEN(rope[i]); - zend_string_release_ex(rope[i], 0); - } - *target = '\0'; + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); - ZEND_VM_NEXT_OPCODE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; + zval *object; + zval *property; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = NULL; - if (Z_ISREF_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } else { - ZVAL_MAKE_REF_EX(expr_ptr, 2); - } - - } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_TMP_VAR) { - /* pass */ - } else if (IS_TMP_VAR == IS_CONST) { - Z_TRY_ADDREF_P(expr_ptr); - } else if (IS_TMP_VAR == IS_CV) { - ZVAL_DEREF(expr_ptr); - Z_TRY_ADDREF_P(expr_ptr); - } else /* if (IS_TMP_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { - zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); - expr_ptr = Z_REFVAL_P(expr_ptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } - } - - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - zend_string *str; - zend_ulong hval; -add_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; +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + if (IS_CONST == IS_CONST) { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + } else { + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); } + + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { - offset = Z_REFVAL_P(offset); - goto add_again; - } else if (Z_TYPE_P(offset) == IS_NULL) { - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else if (Z_TYPE_P(offset) == IS_DOUBLE) { - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - } else if (Z_TYPE_P(offset) == IS_FALSE) { - hval = 0; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_TRUE) { - hval = 1; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_RESOURCE) { - zend_use_resource_as_offset(offset); - hval = Z_RES_HANDLE_P(offset); - goto num_index; - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { - ZVAL_UNDEFINED_OP2(); - str = ZSTR_EMPTY_ALLOC(); - goto str_index; } else { - zend_illegal_offset(); - zval_ptr_dtor_nogc(expr_ptr); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { - zend_cannot_add_element(); - zval_ptr_dtor_nogc(expr_ptr); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } - } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE + zval *container; - array = EX_VAR(opline->result.var); - if (IS_TMP_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - ZVAL_ARR(array, zend_new_array(size)); - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init_mixed(Z_ARRVAL_P(array)); - } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *container; SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* 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) { - if (UNEXPECTED(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)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = NULL; - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_TMP_VAR == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - } - } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_RW(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); - } 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); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - /* Set the new yielded key */ - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { - key = Z_REFVAL_P(key); - } - ZVAL_COPY(&generator->key, key); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.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); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif - 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); + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - generator->send_target = NULL; + if (IS_CONST == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_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(); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; - /* 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(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_UNSET(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); - ZEND_VM_RETURN(); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - zend_bool result; + zval *property, *container, *result; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_VAR, property, IS_CONST, + ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - zend_bool result; + zval *property, *container, *result; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + /* Behave like FETCH_OBJ_W */ + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - if (IS_UNUSED == IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *container, *property, *result; - if (IS_TMP_VAR == IS_UNUSED) { - SAVE_OPLINE(); - zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); - HANDLE_EXCEPTION(); - } else { -/* prevents "undefined variable opline" errors */ -#if 0 || (IS_TMP_VAR != IS_UNUSED) - zval *retval_ref, *retval_ptr; - zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - retval_ref = retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); - retval_ref = retval_ptr = EX_VAR(opline->result.var); - } else if (IS_TMP_VAR == IS_VAR) { - if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { - retval_ptr = Z_INDIRECT_P(retval_ptr); - } - ZVAL_DEREF(retval_ptr); - } else if (IS_TMP_VAR == IS_CV) { - ZVAL_DEREF(retval_ptr); - } + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { - ZEND_VM_NEXT_OPCODE(); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim; - zend_reference *ref = NULL; - void *cache_slot = CACHE_ADDR(opline->op2.num); - if (UNEXPECTED(retval_ref != retval_ptr)) { - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - ref = Z_REF_P(retval_ref); - } else { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); - } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); - } - retval_ptr = retval_ref; - } - } + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = RT_CONSTANT(opline, opline->op2); - SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { - zend_verify_return_error(EX(func), cache_slot, retval_ptr); - HANDLE_EXCEPTION(); - } - ZEND_VM_NEXT_OPCODE(); -#endif + if (IS_VAR == IS_VAR + && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT + && UNEXPECTED(!Z_ISREF_P(container)) + ) { + zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); + zend_fetch_dimension_address_LIST_r(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_fetch_dimension_address_W(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = NULL; - if (Z_ISREF_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } else { - ZVAL_MAKE_REF_EX(expr_ptr, 2); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } - } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_TMP_VAR) { - /* pass */ - } else if (IS_TMP_VAR == IS_CONST) { - Z_TRY_ADDREF_P(expr_ptr); - } else if (IS_TMP_VAR == IS_CV) { - ZVAL_DEREF(expr_ptr); - Z_TRY_ADDREF_P(expr_ptr); - } else /* if (IS_TMP_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { - zend_refcounted *ref = Z_COUNTED_P(expr_ptr); +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; - expr_ptr = Z_REFVAL_P(expr_ptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; + + if (IS_CONST == IS_CONST) { + orig_type = Z_TYPE_P(value); + } + + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_CONST == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); + } + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; } } - } - } - if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; - zend_string *str; - zend_ulong hval; + if (!zobj->ce->__set) { -add_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_UNUSED != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { - offset = Z_REFVAL_P(offset); - goto add_again; - } else if (Z_TYPE_P(offset) == IS_NULL) { - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else if (Z_TYPE_P(offset) == IS_DOUBLE) { - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - } else if (Z_TYPE_P(offset) == IS_FALSE) { - hval = 0; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_TRUE) { - hval = 1; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_RESOURCE) { - zend_use_resource_as_offset(offset); - hval = Z_RES_HANDLE_P(offset); - goto num_index; - } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { - ZVAL_UNDEFINED_OP2(); - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else { - zend_illegal_offset(); - zval_ptr_dtor_nogc(expr_ptr); } + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { - zend_cannot_add_element(); - zval_ptr_dtor_nogc(expr_ptr); + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; } } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zval *array; - uint32_t size; - USE_OPLINE + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - array = EX_VAR(opline->result.var); - if (IS_TMP_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - ZVAL_ARR(array, zend_new_array(size)); - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init_mixed(Z_ARRVAL_P(array)); - } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + +exit_assign_obj: + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; - /* Set the new yielded value */ - if (IS_TMP_VAR != IS_UNUSED) { - if (UNEXPECTED(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)) { - zval *value; + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); + if (IS_TMP_VAR == IS_CONST) { + orig_type = Z_TYPE_P(value); } - } - } else { - zval *value_ptr = NULL; - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_TMP_VAR == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_TMP_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - + goto exit_assign_obj; + } } } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; + } + } - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + goto exit_assign_obj; } } - } 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; - if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { - key = Z_REFVAL_P(key); - } - ZVAL_COPY(&generator->key, 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 (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(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); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); } else { - generator->send_target = NULL; + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } } - /* 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(); -} + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1; - zend_string *type; + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } - SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - type = zend_zval_get_type(op1); - if (EXPECTED(type)) { - ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); - } else { - ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 USE_OPLINE -#endif + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - if (IS_CV == IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_string **rope; - zval *var; +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; - /* op1 and result are the same */ - rope = (zend_string**)EX_VAR(opline->op1.var); - if (IS_CV == IS_CONST) { - var = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - rope[opline->extended_value] = Z_STR_P(var); - if (UNEXPECTED(Z_REFCOUNTED_P(var))) { - Z_ADDREF_P(var); - } - } else { - var = EX_VAR(opline->op2.var); - if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { - if (IS_CV == IS_CV) { - rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); - } else { - rope[opline->extended_value] = Z_STR_P(var); - } - } else { - SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - } - rope[opline->extended_value] = zval_get_string_func(var); + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - } - ZEND_VM_NEXT_OPCODE(); -} + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_string **rope; - zval *var, *ret; - uint32_t i; - size_t len = 0; - char *target; + if (IS_VAR == IS_CONST) { + orig_type = Z_TYPE_P(value); + } - rope = (zend_string**)EX_VAR(opline->op1.var); - if (IS_CV == IS_CONST) { - var = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - rope[opline->extended_value] = Z_STR_P(var); - if (UNEXPECTED(Z_REFCOUNTED_P(var))) { - Z_ADDREF_P(var); - } - } else { - var = EX_VAR(opline->op2.var); - if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { - if (IS_CV == IS_CV) { - rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); - } else { - rope[opline->extended_value] = Z_STR_P(var); - } - } else { - SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - } - rope[opline->extended_value] = zval_get_string_func(var); + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - if (UNEXPECTED(EG(exception))) { - for (i = 0; i <= opline->extended_value; i++) { - zend_string_release_ex(rope[i], 0); + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); + } + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); } - } - } - for (i = 0; i <= opline->extended_value; i++) { - len += ZSTR_LEN(rope[i]); - } - ret = EX_VAR(opline->result.var); - ZVAL_STR(ret, zend_string_alloc(len, 0)); - target = Z_STRVAL_P(ret); - for (i = 0; i <= opline->extended_value; i++) { - memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); - target += ZSTR_LEN(rope[i]); - zend_string_release_ex(rope[i], 0); - } - *target = '\0'; - - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *expr_ptr, new_expr; - - SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = NULL; - if (Z_ISREF_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); } else { - ZVAL_MAKE_REF_EX(expr_ptr, 2); - } - - } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_TMP_VAR) { - /* pass */ - } else if (IS_TMP_VAR == IS_CONST) { - Z_TRY_ADDREF_P(expr_ptr); - } else if (IS_TMP_VAR == IS_CV) { - ZVAL_DEREF(expr_ptr); - Z_TRY_ADDREF_P(expr_ptr); - } else /* if (IS_TMP_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { - zend_refcounted *ref = Z_COUNTED_P(expr_ptr); - - expr_ptr = Z_REFVAL_P(expr_ptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; } } - } - } - if (IS_CV != IS_UNUSED) { - zval *offset = EX_VAR(opline->op2.var); - zend_string *str; - zend_ulong hval; + if (!zobj->ce->__set) { -add_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; + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { - offset = Z_REFVAL_P(offset); - goto add_again; - } else if (Z_TYPE_P(offset) == IS_NULL) { - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else if (Z_TYPE_P(offset) == IS_DOUBLE) { - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - } else if (Z_TYPE_P(offset) == IS_FALSE) { - hval = 0; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_TRUE) { - hval = 1; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_RESOURCE) { - zend_use_resource_as_offset(offset); - hval = Z_RES_HANDLE_P(offset); - goto num_index; - } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { - ZVAL_UNDEFINED_OP2(); - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else { - zend_illegal_offset(); - zval_ptr_dtor_nogc(expr_ptr); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { - zend_cannot_add_element(); - zval_ptr_dtor_nogc(expr_ptr); + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; } } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zval *array; - uint32_t size; - USE_OPLINE + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - array = EX_VAR(opline->result.var); - if (IS_TMP_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - ZVAL_ARR(array, zend_new_array(size)); - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init_mixed(Z_ARRVAL_P(array)); - } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; - /* Set the new yielded value */ - if (IS_TMP_VAR != IS_UNUSED) { - if (UNEXPECTED(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)) { - zval *value; + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); + if (IS_CV == IS_CONST) { + orig_type = Z_TYPE_P(value); } - } - } else { - zval *value_ptr = NULL; - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_TMP_VAR == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_CV == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - + goto exit_assign_obj; + } } } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; + } + } - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + goto exit_assign_obj; } } - } 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(opline->op2.var EXECUTE_DATA_CC); - if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { - key = Z_REFVAL_P(key); - } - ZVAL_COPY(&generator->key, key); + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(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); - } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); } 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); + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } } - 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; + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } - /* 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(); +exit_assign_obj: - ZEND_VM_RETURN(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *closure, *var; + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; - closure = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (opline->extended_value & ZEND_BIND_REF) { - /* By-ref binding */ - var = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); - if (Z_ISREF_P(var)) { - Z_ADDREF_P(var); + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(variable_ptr == NULL)) { + + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CONST == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (value != free_op_data) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } } else { - ZVAL_MAKE_REF_EX(var, 2); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = RT_CONSTANT((opline+1), (opline+1)->op1); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { - var = EX_VAR(opline->op2.var); - if (UNEXPECTED(Z_ISUNDEF_P(var)) && !(opline->extended_value & ZEND_BIND_IMPLICIT)) { - SAVE_OPLINE(); - var = ZVAL_UNDEFINED_OP2(); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; } } - ZVAL_DEREF(var); - Z_TRY_ADDREF_P(var); - } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + dim = RT_CONSTANT(opline, opline->op2); + value = RT_CONSTANT((opline+1), (opline+1)->op1); - zend_closure_bind_var_ex(closure, - (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)), var); - ZEND_VM_NEXT_OPCODE(); -} + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - SAVE_OPLINE(); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { - ZVAL_NULL(var_ptr); - ZVAL_UNDEFINED_OP1(); - } + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); - break; + UNDEF_RESULT(); + } else { + ZVAL_ARR(object_ptr, zend_new_array(8)); + goto try_assign_dim_array; } - } - increment_function(var_ptr); - } while (0); + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } } + if (IS_CONST != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - fast_long_increment_function(var_ptr); - if (UNEXPECTED(0)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_TMP_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (value != free_op_data) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } - ZEND_VM_NEXT_OPCODE(); - } - - ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + dim = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - fast_long_increment_function(var_ptr); - if (UNEXPECTED(1)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + ZVAL_ARR(object_ptr, zend_new_array(8)); + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } } - ZEND_VM_NEXT_OPCODE(); } + if (IS_CONST != IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; SAVE_OPLINE(); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { - ZVAL_NULL(var_ptr); - ZVAL_UNDEFINED_OP1(); - } - - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); - break; + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (value != free_op_data) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } - decrement_function(var_ptr); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; - - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - fast_long_decrement_function(var_ptr); - if (UNEXPECTED(0)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } - ZEND_VM_NEXT_OPCODE(); - } - - ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + dim = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - fast_long_decrement_function(var_ptr); - if (UNEXPECTED(1)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + ZVAL_ARR(object_ptr, zend_new_array(8)); + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } } - ZEND_VM_NEXT_OPCODE(); } + if (IS_CONST != IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; SAVE_OPLINE(); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { - ZVAL_NULL(var_ptr); - ZVAL_UNDEFINED_OP1(); - } + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(variable_ptr == NULL)) { - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); - break; + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CV == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (value != free_op_data) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - - increment_function(var_ptr); - } while (0); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; - - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); - fast_long_increment_function(var_ptr); - ZEND_VM_NEXT_OPCODE(); - } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + dim = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - ZEND_VM_TAIL_CALL(zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); -} + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - SAVE_OPLINE(); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { - ZVAL_NULL(var_ptr); - ZVAL_UNDEFINED_OP1(); - } + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); + UNDEF_RESULT(); + } else { + ZVAL_ARR(object_ptr, zend_new_array(8)); + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); - break; + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } } - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - - decrement_function(var_ptr); - } while (0); + } + if (IS_CONST != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; + zval *value; + zval *variable_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); - fast_long_decrement_function(var_ptr); - ZEND_VM_NEXT_OPCODE(); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ - ZEND_VM_TAIL_CALL(zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *retval_ptr; - zval *return_value; + zval *value; + zval *variable_ptr; - retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - return_value = EX(return_value); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { - SAVE_OPLINE(); - retval_ptr = ZVAL_UNDEFINED_OP1(); - if (return_value) { - ZVAL_NULL(return_value); - } - } else if (!return_value) { - if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { - SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(retval_ptr)); - } - } - } else { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { - ZVAL_COPY_VALUE(return_value, retval_ptr); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { - Z_ADDREF_P(return_value); - } - } - } else if (IS_VAR == IS_CV) { - do { - if (Z_OPT_REFCOUNTED_P(retval_ptr)) { - if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { - if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) { - zend_refcounted *ref = Z_COUNTED_P(retval_ptr); - ZVAL_COPY_VALUE(return_value, retval_ptr); - if (GC_MAY_LEAK(ref)) { - gc_possible_root(ref); - } - ZVAL_NULL(retval_ptr); - break; - } else { - Z_ADDREF_P(retval_ptr); - } - } else { - retval_ptr = Z_REFVAL_P(retval_ptr); - if (Z_OPT_REFCOUNTED_P(retval_ptr)) { - Z_ADDREF_P(retval_ptr); - } - } - } - ZVAL_COPY_VALUE(return_value, retval_ptr); - } while (0); - } else /* if (IS_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { - zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - retval_ptr = Z_REFVAL_P(retval_ptr); - ZVAL_COPY_VALUE(return_value, retval_ptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { - Z_ADDREF_P(retval_ptr); - } - } else { - ZVAL_COPY_VALUE(return_value, retval_ptr); - } - } + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } - ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *retval_ptr; + zval *property, *container, *value_ptr; SAVE_OPLINE(); - do { - if ((IS_VAR & (IS_CONST|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_CC); - if (!EX(return_value)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } else { - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - break; - } - - ZVAL_NEW_REF(EX(return_value), retval_ptr); - if (IS_VAR == IS_CONST) { - Z_TRY_ADDREF_P(retval_ptr); - } - } - break; - } - - retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); - if (IS_VAR == IS_VAR) { - ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { - zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - } else { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } - break; - } - } + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (EX(return_value)) { - if (Z_ISREF_P(retval_ptr)) { - Z_ADDREF_P(retval_ptr); + if (1) { + if (IS_VAR == IS_UNUSED) { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); } else { - ZVAL_MAKE_REF_EX(retval_ptr, 2); - } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); - } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } while (0); - - ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *retval; - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - retval = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - /* Copy return value into generator->retval */ - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { - ZVAL_COPY_VALUE(&generator->retval, retval); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { - Z_ADDREF(generator->retval); - } - } - } else if (IS_VAR == IS_CV) { - ZVAL_COPY_DEREF(&generator->retval, retval); - } else /* if (IS_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(retval))) { - zend_refcounted *ref = Z_COUNTED_P(retval); - - retval = Z_REFVAL_P(retval); - ZVAL_COPY_VALUE(&generator->retval, retval); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(retval)) { - Z_ADDREF_P(retval); + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); } } else { - ZVAL_COPY_VALUE(&generator->retval, retval); + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - /* Close the generator to free up resources */ - zend_generator_close(generator, 1); - - /* Pass execution back to handling code */ - ZEND_VM_RETURN(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; + zval *property, *container, *value_ptr; - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { - SAVE_OPLINE(); - ZVAL_UNDEFINED_OP1(); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_NULL(arg); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } + SAVE_OPLINE(); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); - if (IS_VAR == IS_CV) { - ZVAL_COPY_DEREF(arg, varptr); - } else /* if (IS_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(varptr))) { - zend_refcounted *ref = Z_COUNTED_P(varptr); + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); - varptr = Z_REFVAL_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); + if (1) { + if (IS_VAR == IS_UNUSED) { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); } } else { - ZVAL_COPY_VALUE(arg, varptr); + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - ZEND_VM_NEXT_OPCODE(); -} + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, varptr); + SAVE_OPLINE(); - if (EXPECTED(Z_ISREF_P(varptr))) { - ZEND_VM_NEXT_OPCODE(); + if (IS_VAR == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + + HANDLE_EXCEPTION(); + } + if (IS_CONST != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); } - SAVE_OPLINE(); - ZVAL_NEW_REF(arg, arg); - zend_error(E_NOTICE, "Only variables should be passed by reference"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + if (IS_VAR == IS_CONST && + IS_CONST == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_VAR != IS_CONST && + IS_CONST == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if (IS_CONST != IS_UNUSED) { + function_name = RT_CONSTANT(opline, opline->op2); + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_CONST & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; + HANDLE_EXCEPTION(); + } while (0); + } + } - if (EXPECTED(0)) { - if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, varptr); + HANDLE_EXCEPTION(); + } + if (IS_CONST == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_CONST != IS_CONST) { - if (EXPECTED(Z_ISREF_P(varptr) || - QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); } } else { - if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, varptr); - - if (EXPECTED(Z_ISREF_P(varptr) || - ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - SAVE_OPLINE(); - ZVAL_NEW_REF(arg, arg); - zend_error(E_NOTICE, "Only variables should be passed by reference"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zend_class_entry *ce, *scope; + zend_class_constant *c; + zval *value, *zv; USE_OPLINE - zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(1)) { - if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, varptr); + SAVE_OPLINE(); - if (EXPECTED(Z_ISREF_P(varptr) || - QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); - } - } else { - if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + do { + if (IS_VAR == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } else if (EXPECTED(CACHED_PTR(opline->extended_value))) { + ce = CACHED_PTR(opline->extended_value); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + } else { + if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } } - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, varptr); - - if (EXPECTED(Z_ISREF_P(varptr) || - ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); + zv = zend_hash_find_ex(&ce->constants_table, Z_STR_P(RT_CONSTANT(opline, opline->op2)), 1); + if (EXPECTED(zv != NULL)) { + c = Z_PTR_P(zv); + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { + zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + value = &c->value; + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { + zval_update_constant_ex(value, c->ce); + if (UNEXPECTED(EG(exception) != NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); + } else { + zend_throw_error(NULL, "Undefined class constant '%s::%s'", + ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } - } + } while (0); - SAVE_OPLINE(); - ZVAL_NEW_REF(arg, arg); - zend_error(E_NOTICE, "Only variables should be passed by reference"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; + zval *expr_ptr, new_expr; SAVE_OPLINE(); - varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - if (Z_ISREF_P(varptr)) { - Z_ADDREF_P(varptr); + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - ZVAL_MAKE_REF_EX(varptr, 2); + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } } - ZVAL_REF(arg, Z_REF_P(varptr)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE(); + if (IS_CONST != IS_UNUSED) { + zval *offset = RT_CONSTANT(opline, opline->op2); + zend_string *str; + zend_ulong hval; + +add_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; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_offset(); + zval_ptr_dtor_nogc(expr_ptr); + } + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zval *array; + uint32_t size; USE_OPLINE - zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; - if (EXPECTED(0)) { - if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_var_by_ref; + array = EX_VAR(opline->result.var); + if (IS_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); } - } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_var_by_ref: - ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); } +} - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { - SAVE_OPLINE(); - ZVAL_UNDEFINED_OP1(); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_NULL(arg); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_ulong hval; + zend_string *key; - arg = ZEND_CALL_VAR(EX(call), opline->result.var); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = RT_CONSTANT(opline, opline->op2); - if (IS_VAR == IS_CV) { - ZVAL_COPY_DEREF(arg, varptr); - } else /* if (IS_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(varptr))) { - zend_refcounted *ref = Z_COUNTED_P(varptr); + do { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; - varptr = Z_REFVAL_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +offset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; + } + } +str_index_dim: + if (ht == &EG(symbol_table)) { + zend_delete_global_variable(key); + } else { + zend_hash_del(ht, key); + } + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else { + zend_type_error("Illegal offset type in unset"); + } + break; + } else if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } + } + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + container = ZVAL_UNDEFINED_OP1(); + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = ZVAL_UNDEFINED_OP2(); + } + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; } - } else { - ZVAL_COPY_VALUE(arg, varptr); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); + } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_throw_error(NULL, "Cannot unset string offsets"); } - } + } while (0); - ZEND_VM_NEXT_OPCODE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(1)) { - if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_var_by_ref; - } - } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_var_by_ref: - ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { - SAVE_OPLINE(); - ZVAL_UNDEFINED_OP1(); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_NULL(arg); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - - arg = ZEND_CALL_VAR(EX(call), opline->result.var); + zval *container; + zval *offset; + zend_string *name, *tmp_name; - if (IS_VAR == IS_CV) { - ZVAL_COPY_DEREF(arg, varptr); - } else /* if (IS_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(varptr))) { - zend_refcounted *ref = Z_COUNTED_P(varptr); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = RT_CONSTANT(opline, opline->op2); - varptr = Z_REFVAL_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (Z_TYPE_P(container) != IS_OBJECT) { + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + break; + } + } else { + break; } + } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); } else { - ZVAL_COPY_VALUE(arg, varptr); + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } } - } - - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - - if (UNEXPECTED(Z_ISREF_P(varptr))) { - zend_refcounted *ref = Z_COUNTED_P(varptr); - - varptr = Z_REFVAL_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } - } else { - ZVAL_COPY_VALUE(arg, varptr); - } + } while (0); - ZEND_VM_NEXT_OPCODE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *arg, *param; - SAVE_OPLINE(); + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) { - zend_param_must_be_ref(EX(call)->func, opline->op2.num); + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - arg = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - param = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY(param, arg); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *expr; - zval *result = EX_VAR(opline->result.var); - HashTable *ht; + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + if (UNEXPECTED(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_TMP_VAR)) { + zval *value; - switch (opline->extended_value) { - 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: - ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); - if (IS_VAR & (IS_VAR|IS_CV)) { - ZVAL_DEREF(expr); - } - /* If value is already of correct type, return it directly */ - if (Z_TYPE_P(expr) == opline->extended_value) { - ZVAL_COPY_VALUE(result, expr); + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_VAR != IS_TMP_VAR) { - if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } } + } else { + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - - if (opline->extended_value == IS_ARRAY) { - if (IS_VAR == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { - if (Z_TYPE_P(expr) != IS_NULL) { - ZVAL_ARR(result, zend_new_array(1)); - expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; } - } else { - ZVAL_EMPTY_ARRAY(result); } - } else { - HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST); - if (obj_ht) { - /* fast copy */ - ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht, - (Z_OBJCE_P(expr)->default_properties_count || - Z_OBJ_P(expr)->handlers != &std_object_handlers || - GC_IS_RECURSIVE(obj_ht)))); - zend_release_properties(obj_ht); + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); } else { - ZVAL_EMPTY_ARRAY(result); + ZVAL_MAKE_REF_EX(value_ptr, 2); } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); } + } else if (IS_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - ZEND_ASSERT(opline->extended_value == IS_OBJECT); - ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); - if (Z_TYPE_P(expr) == IS_ARRAY) { - ht = zend_symtable_to_proptable(Z_ARR_P(expr)); - if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { - /* TODO: try not to duplicate immutable arrays as well ??? */ - ht = zend_array_dup(ht); - } - Z_OBJ_P(result)->properties = ht; - } else if (Z_TYPE_P(expr) != IS_NULL) { - Z_OBJ_P(result)->properties = ht = zend_new_array(1); - expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_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); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + zval *key = RT_CONSTANT(opline, opline->op2); + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *array_ptr, *result; + 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); + } - SAVE_OPLINE(); + 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; + } - array_ptr = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { - result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); - if (IS_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(array_ptr); - } - Z_FE_POS_P(result) = 0; + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE(); - } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - zend_object *zobj = Z_OBJ_P(array_ptr); - if (!zobj->ce->get_iterator) { - HashTable *properties; + /* 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(); - result = EX_VAR(opline->result.var); - ZVAL_OBJ(result, zobj); - if (IS_VAR != IS_TMP_VAR) { - GC_ADDREF(zobj); - } - properties = zobj->properties; - if (properties) { - if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(properties); - } - properties = zobj->properties = zend_array_dup(properties); - } - } else { - properties = zobj->handlers->get_properties(zobj); - } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + ZEND_VM_RETURN(); +} - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + zval *result; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } else if (is_empty) { - ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); - } else { - ZEND_VM_NEXT_OPCODE(); - } + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_VAR == IS_CONST); + } else if (opline->extended_value) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + } else { + result = NULL; } + } else if (Z_TYPE_P(op1) <= IS_FALSE) { + result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { - zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_get_type_by_const(Z_TYPE_P(array_ptr))); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + zend_string *key; + zval key_tmp, *val; + + result = NULL; + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { + ZVAL_STR(&key_tmp, key); + if (zend_compare(op1, &key_tmp) == 0) { + result = val; + break; + } + } ZEND_HASH_FOREACH_END(); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref; + zval *object; + zval *property; + zval *value; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { - array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (Z_ISREF_P(array_ref)) { - array_ptr = Z_REFVAL_P(array_ref); - } - } else { - array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - } + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { - if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { - if (array_ptr == array_ref) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; } - Z_ADDREF_P(array_ref); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - } else { - array_ref = EX_VAR(opline->result.var); - ZVAL_NEW_REF(array_ref, array_ptr); - array_ptr = Z_REFVAL_P(array_ref); - } - if (IS_VAR == IS_CONST) { - ZVAL_ARR(array_ptr, zend_array_dup(Z_ARRVAL_P(array_ptr))); - } else { - SEPARATE_ARRAY(array_ptr); + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); - if (IS_VAR == IS_VAR) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } } - ZEND_VM_NEXT_OPCODE(); - } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { - if (array_ptr == array_ref) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } - Z_ADDREF_P(array_ref); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); } else { - array_ptr = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(array_ptr, array_ref); - } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); - } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); - } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + zval *orig_zptr = zptr; + zend_reference *ref; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } - if (IS_VAR == IS_VAR) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } else { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } else if (is_empty) { - ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); - } else { - ZEND_VM_NEXT_OPCODE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + } else { + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr); + } + if (UNEXPECTED(prop_info)) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } } - } - } else { - zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_get_type_by_const(Z_TYPE_P(array_ptr))); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - if (IS_VAR == IS_VAR) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); } - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array; - zval *value; - uint32_t value_type; - HashTable *fe_ht; - HashPosition pos; - Bucket *p; + zval *var_ptr; + zval *value, *container, *dim; - array = EX_VAR(opline->op1.var); SAVE_OPLINE(); - if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { - fe_ht = Z_ARRVAL_P(array); - pos = Z_FE_POS_P(array); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ -fe_fetch_r_exit: - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); +assign_dim_op_new_array: + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; } - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - if (EXPECTED(value_type != IS_UNDEF)) { - if (UNEXPECTED(value_type == IS_INDIRECT)) { - value = Z_INDIRECT_P(value); - value_type = Z_TYPE_INFO_P(value); - if (EXPECTED(value_type != IS_UNDEF)) { - break; - } - } else { + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } + } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); break; } } - pos++; - p++; + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - Z_FE_POS_P(array) = pos + 1; - if (RETURN_VALUE_USED(opline)) { - if (!p->key) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + } else { + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; } } - } else { - zend_object_iterator *iter; - - ZEND_ASSERT(Z_TYPE_P(array) == IS_OBJECT); - if ((iter = zend_iterator_unwrap(array)) == NULL) { - /* plain object */ - fe_ht = Z_OBJPROP_P(array); - pos = zend_hash_iterator_pos(Z_FE_ITER_P(array), fe_ht); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - goto fe_fetch_r_exit; - } + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - if (EXPECTED(value_type != IS_UNDEF)) { - if (UNEXPECTED(value_type == IS_INDIRECT)) { - value = Z_INDIRECT_P(value); - value_type = Z_TYPE_INFO_P(value); - if (EXPECTED(value_type != IS_UNDEF) - && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) { - break; - } - } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0) - || !p->key - || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) { - break; - } - } - pos++; - p++; + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; } - if (RETURN_VALUE_USED(opline)) { - if (UNEXPECTED(!p->key)) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else if (ZSTR_VAL(p->key)[0]) { - ZVAL_STR_COPY(EX_VAR(opline->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->result.var), prop_name, prop_name_len); - } + zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - EG(ht_iterators)[Z_FE_ITER_P(array)].pos = pos + 1; + ZVAL_ARR(container, zend_new_array(8)); + goto assign_dim_op_new_array; } else { - if (EXPECTED(++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); - if (UNEXPECTED(EG(exception) != NULL)) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(iter->funcs->valid(iter) == FAILURE)) { - /* reached end of iteration */ - if (UNEXPECTED(EG(exception) != NULL)) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - goto fe_fetch_r_exit; - } - } - value = iter->funcs->get_current_data(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - if (!value) { - /* failure in get_current_data */ - goto fe_fetch_r_exit; - } - if (RETURN_VALUE_USED(opline)) { - if (iter->funcs->get_current_key) { - iter->funcs->get_current_key(iter, EX_VAR(opline->result.var)); - if (UNEXPECTED(EG(exception) != NULL)) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - } else { - ZVAL_LONG(EX_VAR(opline->result.var), iter->index); - } + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } - value_type = Z_TYPE_INFO_P(value); } } - if (EXPECTED(opline->op2_type == IS_CV)) { - zval *variable_ptr = EX_VAR(opline->op2.var); - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zval *res = EX_VAR(opline->op2.var); - zend_refcounted *gc = Z_COUNTED_P(value); - - ZVAL_COPY_VALUE_EX(res, value, gc, value_type); - if (Z_TYPE_INFO_REFCOUNTED(value_type)) { - GC_ADDREF(gc); - } - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array; + zval *var_ptr; zval *value; - uint32_t value_type; - HashTable *fe_ht; - HashPosition pos; - Bucket *p; - array = EX_VAR(opline->op1.var); SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - ZVAL_DEREF(array); - if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { - pos = zend_hash_iterator_pos_ex(Z_FE_ITER_P(EX_VAR(opline->op1.var)), array); - fe_ht = Z_ARRVAL_P(array); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - goto fe_fetch_w_exit; - } - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - if (EXPECTED(value_type != IS_UNDEF)) { - if (UNEXPECTED(value_type == IS_INDIRECT)) { - value = Z_INDIRECT_P(value); - value_type = Z_TYPE_INFO_P(value); - if (EXPECTED(value_type != IS_UNDEF)) { - break; - } - } else { - break; - } - } - pos++; - p++; - } - if (RETURN_VALUE_USED(opline)) { - if (!p->key) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } } - EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; - } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { - zend_object_iterator *iter; + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); - if ((iter = zend_iterator_unwrap(array)) == NULL) { - /* plain object */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } - fe_ht = Z_OBJPROP_P(array); - pos = zend_hash_iterator_pos(Z_FE_ITER_P(EX_VAR(opline->op1.var)), fe_ht); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - goto fe_fetch_w_exit; - } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - if (EXPECTED(value_type != IS_UNDEF)) { - if (UNEXPECTED(value_type == IS_INDIRECT)) { - value = Z_INDIRECT_P(value); - value_type = Z_TYPE_INFO_P(value); - if (EXPECTED(value_type != IS_UNDEF) - && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) { - if ((value_type & Z_TYPE_MASK) != IS_REFERENCE) { - zend_property_info *prop_info = - zend_get_typed_property_info_for_slot(Z_OBJ_P(array), value); - if (UNEXPECTED(prop_info)) { - ZVAL_NEW_REF(value, value); - ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(value), prop_info); - value_type = IS_REFERENCE_EX; - } - } - break; - } - } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0) - || !p->key - || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) { - break; - } - } - pos++; - p++; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; } - if (RETURN_VALUE_USED(opline)) { - if (UNEXPECTED(!p->key)) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else if (ZSTR_VAL(p->key)[0]) { - ZVAL_STR_COPY(EX_VAR(opline->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->result.var), prop_name, prop_name_len); - } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); } else { - if (++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); - if (UNEXPECTED(EG(exception) != NULL)) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(iter->funcs->valid(iter) == FAILURE)) { - /* reached end of iteration */ - if (UNEXPECTED(EG(exception) != NULL)) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - goto fe_fetch_w_exit; - } - } - value = iter->funcs->get_current_data(iter); - if (UNEXPECTED(EG(exception) != NULL)) { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - if (!value) { - /* failure in get_current_data */ - goto fe_fetch_w_exit; + break; } - if (RETURN_VALUE_USED(opline)) { - if (iter->funcs->get_current_key) { - iter->funcs->get_current_key(iter, EX_VAR(opline->result.var)); - if (UNEXPECTED(EG(exception) != NULL)) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); } else { - ZVAL_LONG(EX_VAR(opline->result.var), iter->index); + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); } + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } - value_type = Z_TYPE_INFO_P(value); + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); } - } else { - zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_get_type_by_const(Z_TYPE_P(array))); - if (UNEXPECTED(EG(exception))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } -fe_fetch_w_exit: - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); - } - - if (EXPECTED((value_type & Z_TYPE_MASK) != IS_REFERENCE)) { - zend_refcounted *gc = Z_COUNTED_P(value); - zval *ref; - ZVAL_NEW_EMPTY_REF(value); - ref = Z_REFVAL_P(value); - ZVAL_COPY_VALUE_EX(ref, value, gc, value_type); - } - if (EXPECTED(opline->op2_type == IS_CV)) { - zval *variable_ptr = EX_VAR(opline->op2.var); - if (EXPECTED(variable_ptr != value)) { - zend_reference *ref; + } while (0); - ref = Z_REF_P(value); - GC_ADDREF(ref); - i_zval_ptr_dtor(variable_ptr); - ZVAL_REF(variable_ptr, ref); - } - } else { - Z_ADDREF_P(value); - ZVAL_REF(EX_VAR(opline->op2.var), Z_REF_P(value)); - } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - zval *ref = NULL; - int ret; + zval *object; + zval *property; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { - if (IS_VAR == IS_VAR) { - ref = value; + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } - value = Z_REFVAL_P(value); - } - - ret = i_zend_is_true(value); - - if (UNEXPECTED(EG(exception))) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - - if (ret) { - zval *result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if (IS_VAR == IS_VAR && ref) { - zend_reference *r = Z_REF_P(ref); +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + } else { + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); + } - if (UNEXPECTED(GC_DELREF(r) == 0)) { - efree_size(r, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(result); + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); } - ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); - } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - zval *ref = NULL; + zval *container; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - if (IS_VAR & IS_VAR) { - ref = value; - } - value = Z_REFVAL_P(value); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - if (Z_TYPE_P(value) > IS_NULL) { - zval *result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if ((IS_VAR & IS_VAR) && ref) { - zend_reference *r = Z_REF_P(ref); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; - if (UNEXPECTED(GC_DELREF(r) == 0)) { - efree_size(r, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(result); - } - } - ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 USE_OPLINE - zval *value; - zval *result = EX_VAR(opline->result.var); - - value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - SAVE_OPLINE(); - ZVAL_UNDEFINED_OP1(); - ZVAL_NULL(result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } +#endif - if (IS_VAR == IS_CV) { - ZVAL_COPY_DEREF(result, value); - } else if (IS_VAR == IS_VAR) { - if (UNEXPECTED(Z_ISREF_P(value))) { - ZVAL_COPY_VALUE(result, Z_REFVAL_P(value)); - if (UNEXPECTED(Z_DELREF_P(value) == 0)) { - efree_size(Z_REF_P(value), sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(result); - } - } else { - ZVAL_COPY_VALUE(result, value); - } + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - ZVAL_COPY_VALUE(result, value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { - Z_ADDREF_P(result); - } + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; - - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); + zval *container; - if (IS_VAR == IS_CV) { - ZVAL_COPY(arg, varptr); - } else /* if (IS_VAR == IS_VAR) */ { - ZVAL_COPY_VALUE(arg, varptr); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } - - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; + zval *property, *container, *result; - if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), + (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; - if (IS_VAR == IS_CV) { - ZVAL_COPY(arg, varptr); - } else /* if (IS_VAR == IS_VAR) */ { - ZVAL_COPY_VALUE(arg, varptr); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - ZEND_VM_NEXT_OPCODE(); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - zend_bool result; + zval *container, *property, *result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - op2 = RT_CONSTANT(opline, opline->op2); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_SMART_BRANCH(result, 1); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - zend_bool result; + zval *container, *dim; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - op2 = RT_CONSTANT(opline, opline->op2); - result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - ZEND_VM_SMART_BRANCH(result, 1); + if (IS_VAR == IS_VAR + && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT + && UNEXPECTED(!Z_ISREF_P(container)) + ) { + zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); + zend_fetch_dimension_address_LIST_r(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_fetch_dimension_address_W(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - zval *value, *container, *dim; + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { -assign_dim_op_array: - SEPARATE_ARRAY(container); -assign_dim_op_new_array: - dim = RT_CONSTANT(opline, opline->op2); - if (IS_CONST == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); - if (UNEXPECTED(!var_ptr)) { - zend_cannot_add_element(); - goto assign_dim_op_ret_null; + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; + + if (IS_CONST == IS_CONST) { + orig_type = Z_TYPE_P(value); + } + + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_CONST == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); + } + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } } } else { - if (IS_CONST == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); - } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); - } - if (UNEXPECTED(!var_ptr)) { - goto assign_dim_op_ret_null; + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; + } } - } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + if (!zobj->ce->__set) { - do { - if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + goto exit_assign_obj; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); } else { - if (EXPECTED(Z_ISREF_P(container))) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto assign_dim_op_array; - } + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; } + } - dim = RT_CONSTANT(opline, opline->op2); + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); - } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - ZVAL_ARR(container, zend_new_array(8)); - goto assign_dim_op_new_array; - } else { - zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); -assign_dim_op_ret_null: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + +exit_assign_obj: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - zval *value; + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - value = RT_CONSTANT(opline, opline->op2); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; + + if (IS_TMP_VAR == IS_CONST) { + orig_type = Z_TYPE_P(value); + } + + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_TMP_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); + } + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; + zval *object, *property, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - do { - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto post_incdec_object; - } - if (IS_VAR == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } -post_incdec_object: - /* here we are sure we are dealing with an object */ - zobj = Z_OBJ_P(object); - if (IS_CONST == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - break; - } - } - cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - if (IS_CONST == IS_CONST) { - prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; + + if (IS_VAR == IS_CONST) { + orig_type = Z_TYPE_P(value); + } + + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); + } + goto free_and_exit_assign_obj; } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } - - zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } } - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; } - } while (0); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_RW(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif + if (IS_CV == IS_CONST) { + orig_type = Z_TYPE_P(value); + } - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - if (IS_CONST == IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } -} + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_CV == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); + } + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; + } + } - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_UNSET(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + if (!zobj->ce->__set) { - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *property, *result; + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - result = EX_VAR(opline->result.var); - zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + UNDEF_RESULT(); + goto exit_assign_obj; + } } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *dim; + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - dim = RT_CONSTANT(opline, opline->op2); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } - if (IS_VAR == IS_VAR - && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT - && UNEXPECTED(!Z_ISREF_P(container)) - ) { - zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); - zend_fetch_dimension_address_LIST_r(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_fetch_dimension_address_W(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +exit_assign_obj: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -23847,7 +24347,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if (IS_CONST == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); @@ -23875,8 +24375,8 @@ try_assign_dim_array: } } } else { - dim = RT_CONSTANT(opline, opline->op2); - if (IS_CONST == IS_CONST) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); @@ -23898,21 +24398,21 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if (IS_CONST == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); UNDEF_RESULT(); } else { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -23921,7 +24421,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -23930,7 +24430,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -23938,15 +24438,15 @@ assign_dim_error: } } } - if (IS_CONST != IS_UNUSED) { - + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -23960,7 +24460,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if (IS_CONST == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); @@ -23988,8 +24488,8 @@ try_assign_dim_array: } } } else { - dim = RT_CONSTANT(opline, opline->op2); - if (IS_CONST == IS_CONST) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); @@ -24011,22 +24511,22 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if (IS_CONST == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -24035,7 +24535,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -24044,7 +24544,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -24052,15 +24552,15 @@ assign_dim_error: } } } - if (IS_CONST != IS_UNUSED) { - + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -24074,7 +24574,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if (IS_CONST == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); @@ -24102,8 +24602,8 @@ try_assign_dim_array: } } } else { - dim = RT_CONSTANT(opline, opline->op2); - if (IS_CONST == IS_CONST) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); @@ -24125,22 +24625,22 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if (IS_CONST == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -24149,7 +24649,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -24158,7 +24658,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -24166,15 +24666,15 @@ assign_dim_error: } } } - if (IS_CONST != IS_UNUSED) { - + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -24188,7 +24688,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if (IS_CONST == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CV || IS_CV == IS_VAR) { ZVAL_DEREF(value); @@ -24216,8 +24716,8 @@ try_assign_dim_array: } } } else { - dim = RT_CONSTANT(opline, opline->op2); - if (IS_CONST == IS_CONST) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); @@ -24239,21 +24739,21 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if (IS_CONST == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); UNDEF_RESULT(); } else { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -24262,7 +24762,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -24271,7 +24771,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = RT_CONSTANT(opline, opline->op2); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -24279,55 +24779,89 @@ assign_dim_error: } } } - if (IS_CONST != IS_UNUSED) { - + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - zval *variable_ptr; + zval *property, *container, *value_ptr; SAVE_OPLINE(); - value = RT_CONSTANT(opline, opline->op2); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_VAR == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - zval *variable_ptr; + zval *property, *container, *value_ptr; SAVE_OPLINE(); - value = RT_CONSTANT(opline, opline->op2); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_VAR == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -24345,10 +24879,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { ZEND_ASSERT(EG(exception)); - + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } - if (IS_CONST != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { CACHE_PTR(opline->result.num, ce); } } @@ -24356,7 +24890,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { ZEND_ASSERT(EG(exception)); - + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } } else { @@ -24364,31 +24898,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } if (IS_VAR == IS_CONST && - IS_CONST == IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_VAR != IS_CONST && - IS_CONST == IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); - } else if (IS_CONST != IS_UNUSED) { - function_name = RT_CONSTANT(opline, opline->op2); - if (IS_CONST != IS_CONST) { + } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { - if (IS_CONST & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { break; } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); - + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); } @@ -24397,24 +24931,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (ce->get_static_method) { fbc = ce->get_static_method(ce, Z_STR_P(function_name)); } else { - fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { zend_undefined_method(ce, Z_STR_P(function_name)); } - + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } - if (IS_CONST == IS_CONST && + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); } - if (IS_CONST != IS_CONST) { - + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -24461,79 +24995,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zend_class_entry *ce, *scope; - zend_class_constant *c; - zval *value, *zv; - USE_OPLINE - - SAVE_OPLINE(); - - do { - if (IS_VAR == IS_CONST) { - if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { - value = CACHED_PTR(opline->extended_value + sizeof(void*)); - break; - } else if (EXPECTED(CACHED_PTR(opline->extended_value))) { - ce = CACHED_PTR(opline->extended_value); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); - if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } - } else { - if (IS_VAR == IS_UNUSED) { - ce = zend_fetch_class(NULL, opline->op1.num); - if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - } - if (EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { - value = CACHED_PTR(opline->extended_value + sizeof(void*)); - break; - } - } - - zv = zend_hash_find_ex(&ce->constants_table, Z_STR_P(RT_CONSTANT(opline, opline->op2)), 1); - if (EXPECTED(zv != NULL)) { - c = Z_PTR_P(zv); - scope = EX(func)->op_array.scope; - if (!zend_verify_const_access(c, scope)) { - zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - value = &c->value; - if (Z_TYPE_P(value) == IS_CONSTANT_AST) { - zval_update_constant_ex(value, c->ce); - if (UNEXPECTED(EG(exception) != NULL)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } - CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); - } else { - zend_throw_error(NULL, "Undefined class constant '%s::%s'", - ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } while (0); - - ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); - - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -24573,15 +25035,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON } } - if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zend_string *str; zend_ulong hval; add_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; } @@ -24592,7 +25054,7 @@ str_index: hval = Z_LVAL_P(offset); num_index: zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { offset = Z_REFVAL_P(offset); goto add_again; } else if (Z_TYPE_P(offset) == IS_NULL) { @@ -24611,7 +25073,7 @@ num_index: zend_use_resource_as_offset(offset); hval = Z_RES_HANDLE_P(offset); goto num_index; - } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { ZVAL_UNDEFINED_OP2(); str = ZSTR_EMPTY_ALLOC(); goto str_index; @@ -24619,7 +25081,7 @@ num_index: zend_illegal_offset(); zval_ptr_dtor_nogc(expr_ptr); } - + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -24629,7 +25091,7 @@ num_index: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -24643,14 +25105,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HAND if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init_mixed(Z_ARRVAL_P(array)); } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { ZVAL_ARR(array, zend_new_array(0)); ZEND_VM_NEXT_OPCODE(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -24660,7 +25122,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDL SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = RT_CONSTANT(opline, opline->op2); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -24672,7 +25134,7 @@ unset_dim_array: offset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { key = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } @@ -24687,7 +25149,7 @@ str_index_dim: hval = Z_LVAL_P(offset); num_index_dim: zend_hash_index_del(ht, hval); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { offset = Z_REFVAL_P(offset); goto offset_again; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -24705,7 +25167,7 @@ num_index_dim: } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); goto num_index_dim; - } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { ZVAL_UNDEFINED_OP2(); key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; @@ -24722,11 +25184,11 @@ num_index_dim: if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { container = ZVAL_UNDEFINED_OP1(); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { offset = ZVAL_UNDEFINED_OP2(); } if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); @@ -24735,11 +25197,12 @@ num_index_dim: } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -24748,7 +25211,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = RT_CONSTANT(opline, opline->op2); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { @@ -24765,7 +25228,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL break; } } - if (IS_CONST == IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { name = Z_STR_P(offset); } else { name = zval_try_get_tmp_string(offset, &tmp_name); @@ -24773,17 +25236,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); - if (IS_CONST != IS_CONST) { + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_tmp_string_release(tmp_name); } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -24869,12 +25333,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z } /* Set the new yielded key */ - if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -24907,43 +25372,182 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; - HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); - zval *result; + zval *op1, *op2; + zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_VAR == IS_CONST); - } else if (opline->extended_value) { - if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { - result = zend_hash_index_find(ht, Z_LVAL_P(op1)); - } else { - result = NULL; + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *variable_ptr; + zval *value_ptr; + + SAVE_OPLINE(); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { + + zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); + variable_ptr = &EG(uninitialized_zval); + } else if (IS_VAR == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!Z_ISREF_P(value_ptr))) { + + if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { + variable_ptr = &EG(uninitialized_zval); } - } else if (Z_TYPE_P(op1) <= IS_FALSE) { - result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { - zend_string *key; - zval key_tmp, *val; + zend_assign_to_variable_reference(variable_ptr, value_ptr); + } - result = NULL; - ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { - ZVAL_STR(&key_tmp, key); - if (zend_compare(op1, &key_tmp) == 0) { - result = val; - break; - } - } ZEND_HASH_FOREACH_END(); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -24956,15 +25560,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_ assign_dim_op_array: SEPARATE_ARRAY(container); assign_dim_op_new_array: - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + dim = NULL; + if (IS_UNUSED == IS_UNUSED) { var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); goto assign_dim_op_ret_null; } } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (IS_UNUSED == IS_CONST) { var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); } else { var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); @@ -24977,7 +25581,7 @@ assign_dim_op_new_array: value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { zend_reference *ref = Z_REF_P(var_ptr); var_ptr = Z_REFVAL_P(var_ptr); if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { @@ -24997,165 +25601,66 @@ assign_dim_op_new_array: container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { goto assign_dim_op_array; - } - } - - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - - if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); - } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - ZVAL_ARR(container, zend_new_array(8)); - goto assign_dim_op_new_array; - } else { - zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); -assign_dim_op_ret_null: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } - } - - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_EX(1, 2); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; - zval *value; - - SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - - do { - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto post_incdec_object; - } - if (IS_VAR == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; - } - -post_incdec_object: - /* here we are sure we are dealing with an object */ - zobj = Z_OBJ_P(object); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - break; - } - } - cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); - } + } + } - zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + dim = NULL; + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; } + zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ZVAL_ARR(container, zend_new_array(8)); + goto assign_dim_op_new_array; } else { - zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); - } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } } - } while (0); + } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zend_fetch_dimension_address_W(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zend_fetch_dimension_address_RW(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -25165,71 +25670,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TM if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *property, *result; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - result = EX_VAR(opline->result.var); - zend_fetch_property_address(result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *dim; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR - && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT - && UNEXPECTED(!Z_ISREF_P(container)) - ) { - zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); - zend_fetch_dimension_address_LIST_r(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_fetch_dimension_address_W(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -25243,7 +25693,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); @@ -25271,8 +25721,8 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + dim = NULL; + if (IS_UNUSED == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); @@ -25294,21 +25744,21 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; value = RT_CONSTANT((opline+1), (opline+1)->op1); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -25317,7 +25767,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; UNDEF_RESULT(); } else { @@ -25326,7 +25776,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25334,15 +25784,15 @@ assign_dim_error: } } } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_UNUSED != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -25356,7 +25806,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); @@ -25384,8 +25834,8 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + dim = NULL; + if (IS_UNUSED == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); @@ -25407,22 +25857,22 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -25431,7 +25881,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -25440,7 +25890,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25448,15 +25898,15 @@ assign_dim_error: } } } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_UNUSED != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -25470,7 +25920,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); @@ -25498,8 +25948,8 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + dim = NULL; + if (IS_UNUSED == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); @@ -25521,22 +25971,22 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -25545,7 +25995,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -25554,7 +26004,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25562,15 +26012,15 @@ assign_dim_error: } } } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_UNUSED != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -25584,7 +26034,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CV || IS_CV == IS_VAR) { ZVAL_DEREF(value); @@ -25612,8 +26062,8 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + dim = NULL; + if (IS_UNUSED == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); @@ -25635,21 +26085,21 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -25658,7 +26108,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; UNDEF_RESULT(); } else { @@ -25667,7 +26117,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25675,15 +26125,15 @@ assign_dim_error: } } } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_UNUSED != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -25701,10 +26151,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (IS_UNUSED != IS_CONST) { CACHE_PTR(opline->result.num, ce); } } @@ -25712,7 +26162,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } } else { @@ -25720,31 +26170,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } if (IS_VAR == IS_CONST && - (IS_TMP_VAR|IS_VAR) == IS_CONST && + IS_UNUSED == IS_CONST && EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_VAR != IS_CONST && - (IS_TMP_VAR|IS_VAR) == IS_CONST && + IS_UNUSED == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); - } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + } else if (IS_UNUSED != IS_UNUSED) { + function_name = NULL; + if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { - if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + if (IS_UNUSED & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { break; } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } while (0); } @@ -25753,24 +26203,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (ce->get_static_method) { fbc = ce->get_static_method(ce, Z_STR_P(function_name)); } else { - fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { zend_undefined_method(ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + if (IS_UNUSED == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_UNUSED != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -25817,7 +26267,136 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (IS_VAR == IS_UNUSED) { + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + HANDLE_EXCEPTION(); + } else { +/* prevents "undefined variable opline" errors */ +#if 0 || (IS_VAR != IS_UNUSED) + zval *retval_ref, *retval_ptr; + zend_arg_info *ret_info = EX(func)->common.arg_info - 1; + retval_ref = retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_VAR == IS_CONST) { + ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); + retval_ref = retval_ptr = EX_VAR(opline->result.var); + } else if (IS_VAR == IS_VAR) { + if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { + retval_ptr = Z_INDIRECT_P(retval_ptr); + } + ZVAL_DEREF(retval_ptr); + } else if (IS_VAR == IS_CV) { + ZVAL_DEREF(retval_ptr); + } + + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); + } else { + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; + } + } + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), cache_slot, retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +#endif + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *result; + zend_function *constructor; + zend_class_entry *ce; + zend_execute_data *call; + + SAVE_OPLINE(); + if (IS_VAR == IS_CONST) { + ce = CACHED_PTR(opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->op2.num, ce); + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + result = EX_VAR(opline->result.var); + if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) { + ZVAL_UNDEF(result); + HANDLE_EXCEPTION(); + } + + constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); + if (constructor == NULL) { + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + + /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next + * opcode is DO_FCALL in case EXT instructions are used. */ + if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) { + ZEND_VM_NEXT_OPCODE_EX(1, 2); + } + + /* Perform a dummy function call */ + call = zend_vm_stack_push_call_frame( + ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, + opline->extended_value, NULL); + } else { + if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { + init_func_run_time_cache(&constructor->op_array); + } + /* We are not handling overloaded classes right now */ + call = zend_vm_stack_push_call_frame( + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS, + constructor, + opline->extended_value, + Z_OBJ_P(result)); + Z_ADDREF_P(result); + } + + call->prev_execute_data = EX(call); + EX(call) = call; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -25857,15 +26436,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP } } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (IS_UNUSED != IS_UNUSED) { + zval *offset = NULL; zend_string *str; zend_ulong hval; add_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (IS_UNUSED != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index; } @@ -25875,201 +26454,81 @@ str_index: } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { hval = Z_LVAL_P(offset); num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { - offset = Z_REFVAL_P(offset); - goto add_again; - } else if (Z_TYPE_P(offset) == IS_NULL) { - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else if (Z_TYPE_P(offset) == IS_DOUBLE) { - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - } else if (Z_TYPE_P(offset) == IS_FALSE) { - hval = 0; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_TRUE) { - hval = 1; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_RESOURCE) { - zend_use_resource_as_offset(offset); - hval = Z_RES_HANDLE_P(offset); - goto num_index; - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { - ZVAL_UNDEFINED_OP2(); - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else { - zend_illegal_offset(); - zval_ptr_dtor_nogc(expr_ptr); - } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { - zend_cannot_add_element(); - zval_ptr_dtor_nogc(expr_ptr); - } - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET 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_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - ZVAL_ARR(array, zend_new_array(size)); - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init_mixed(Z_ARRVAL_P(array)); - } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - zval *offset; - zend_ulong hval; - zend_string *key; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - - do { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; - -unset_dim_array: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); -offset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - key = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(key, hval)) { - goto num_index_dim; - } - } -str_index_dim: - if (ht == &EG(symbol_table)) { - zend_delete_global_variable(key); - } else { - zend_hash_del(ht, key); - } - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { - offset = Z_REFVAL_P(offset); - goto offset_again; - } else if (Z_TYPE_P(offset) == IS_DOUBLE) { - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_dim; - } else if (Z_TYPE_P(offset) == IS_NULL) { - key = ZSTR_EMPTY_ALLOC(); - goto str_index_dim; - } else if (Z_TYPE_P(offset) == IS_FALSE) { - hval = 0; - goto num_index_dim; - } else if (Z_TYPE_P(offset) == IS_TRUE) { - hval = 1; - goto num_index_dim; - } else if (Z_TYPE_P(offset) == IS_RESOURCE) { - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { - ZVAL_UNDEFINED_OP2(); - key = ZSTR_EMPTY_ALLOC(); - goto str_index_dim; - } else { - zend_type_error("Illegal offset type in unset"); - } - break; - } else if (Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto unset_dim_array; - } - } - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - container = ZVAL_UNDEFINED_OP1(); - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { - offset = ZVAL_UNDEFINED_OP2(); - } - if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { - offset++; - } - Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); - } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_throw_error(NULL, "Cannot unset string offsets"); + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_offset(); + zval_ptr_dtor_nogc(expr_ptr); } - } while (0); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zval *array; + uint32_t size; USE_OPLINE - zval *container; - zval *offset; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - do { - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { - if (Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (Z_TYPE_P(container) != IS_OBJECT) { - if (IS_VAR == IS_CV - && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - break; - } - } else { - break; - } - } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(offset); - } else { - name = zval_try_get_tmp_string(offset, &tmp_name); - if (UNEXPECTED(!name)) { - break; - } + array = EX_VAR(opline->result.var); + if (IS_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); } - Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + if (UNEXPECTED(Z_ISREF_P(var_ptr))) { + if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { + ZVAL_UNREF(var_ptr); } - } while (0); + } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -26155,13 +26614,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER( } /* Set the new yielded key */ - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if (IS_UNUSED != IS_UNUSED) { + zval *key = NULL; + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -26194,1619 +26652,1138 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER( ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *variable_ptr; - zval *value_ptr; - - SAVE_OPLINE(); - value_ptr = _get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { - - zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); - variable_ptr = &EG(uninitialized_zval); - } else if (IS_VAR == IS_VAR && - opline->extended_value == ZEND_RETURNS_FUNCTION && - UNEXPECTED(!Z_ISREF_P(value_ptr))) { - - if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { - variable_ptr = &EG(uninitialized_zval); - } - } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); - } - - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; - zval *value, *container, *dim; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { -assign_dim_op_array: - SEPARATE_ARRAY(container); -assign_dim_op_new_array: - dim = NULL; - if (IS_UNUSED == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); - if (UNEXPECTED(!var_ptr)) { - zend_cannot_add_element(); - goto assign_dim_op_ret_null; - } - } else { - if (IS_UNUSED == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); - } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); - } - if (UNEXPECTED(!var_ptr)) { - goto assign_dim_op_ret_null; - } - } - - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - - do { - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - } else { - if (EXPECTED(Z_ISREF_P(container))) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto assign_dim_op_array; - } - } - - dim = NULL; - - if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); - } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - ZVAL_ARR(container, zend_new_array(8)); - goto assign_dim_op_new_array; - } else { - zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); -assign_dim_op_ret_null: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } - } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_EX(1, 2); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_W(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_RW(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif - - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - if (IS_UNUSED == IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zval *value; - zval *variable_ptr; - zval *dim; - - SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { -try_assign_dim_array: - SEPARATE_ARRAY(object_ptr); - if (IS_UNUSED == IS_UNUSED) { - value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - ZVAL_DEREF(value); - } - variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); - if (UNEXPECTED(variable_ptr == NULL)) { + zval *op1 = EX_VAR(opline->op1.var); - zend_cannot_add_element(); - goto assign_dim_error; - } else if (IS_CONST == IS_CV) { - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - } else if (IS_CONST == IS_VAR) { - zval *free_op_data = EX_VAR((opline+1)->op1.var); - if (value != free_op_data) { - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - zval_ptr_dtor_nogc(free_op_data); - } - } else if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } + if (IS_VAR == IS_CV) { + if (UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_NEW_EMPTY_REF(op1); + Z_SET_REFCOUNT_P(op1, 2); + ZVAL_NULL(Z_REFVAL_P(op1)); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); } else { - dim = NULL; - if (IS_UNUSED == IS_CONST) { - variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); - } else { - variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); - } - if (UNEXPECTED(variable_ptr == NULL)) { - goto assign_dim_error; - } - value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - } else { - if (EXPECTED(Z_ISREF_P(object_ptr))) { - object_ptr = Z_REFVAL_P(object_ptr); - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { - goto try_assign_dim_array; - } - } - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = RT_CONSTANT((opline+1), (opline+1)->op1); - - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - - } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if (IS_UNUSED == IS_UNUSED) { - zend_use_new_element_for_string(); - - UNDEF_RESULT(); - } else { - dim = NULL; - value = RT_CONSTANT((opline+1), (opline+1)->op1); - zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - - } - } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_ISREF_P(orig_object_ptr) - && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) - && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = NULL; - - UNDEF_RESULT(); + if (Z_ISREF_P(op1)) { + Z_ADDREF_P(op1); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); - goto try_assign_dim_array; + ZVAL_MAKE_REF_EX(op1, 2); } + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) { + op1 = Z_INDIRECT_P(op1); + if (EXPECTED(!Z_ISREF_P(op1))) { + ZVAL_MAKE_REF_EX(op1, 2); } else { - zend_use_scalar_as_array(); - dim = NULL; -assign_dim_error: - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } + GC_ADDREF(Z_REF_P(op1)); } + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); + } else { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1); } - if (IS_UNUSED != IS_UNUSED) { + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_string *type; + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + type = zend_zval_get_type(op1); + if (EXPECTED(type)) { + ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); + } else { + ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_dim has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; + zval *object; + zval *property; zval *value; - zval *variable_ptr; - zval *dim; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { -try_assign_dim_array: - SEPARATE_ARRAY(object_ptr); - if (IS_UNUSED == IS_UNUSED) { - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(value); - } - variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); - if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - zend_cannot_add_element(); - goto assign_dim_error; - } else if (IS_TMP_VAR == IS_CV) { - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - } else if (IS_TMP_VAR == IS_VAR) { - zval *free_op_data = EX_VAR((opline+1)->op1.var); - if (value != free_op_data) { - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - zval_ptr_dtor_nogc(free_op_data); - } - } else if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } - } else { - dim = NULL; - if (IS_UNUSED == IS_CONST) { - variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); - } else { - variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); - } - if (UNEXPECTED(variable_ptr == NULL)) { - goto assign_dim_error; + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; } - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - } else { - if (EXPECTED(Z_ISREF_P(object_ptr))) { - object_ptr = Z_REFVAL_P(object_ptr); - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { - goto try_assign_dim_array; + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if (IS_UNUSED == IS_UNUSED) { - zend_use_new_element_for_string(); - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { UNDEF_RESULT(); - } else { - dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + break; } - } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_ISREF_P(orig_object_ptr) - && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) - && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = NULL; - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); - goto try_assign_dim_array; + zval *orig_zptr = zptr; + zend_reference *ref; + + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + if (IS_CV == IS_CONST) { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + } else { + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr); + } + if (UNEXPECTED(prop_info)) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } } } else { - zend_use_scalar_as_array(); - dim = NULL; -assign_dim_error: - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); } - } - if (IS_UNUSED != IS_UNUSED) { + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_dim has two opcodes! */ + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zval *value; - zval *variable_ptr; - zval *dim; + zval *var_ptr; + zval *value, *container, *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { -try_assign_dim_array: - SEPARATE_ARRAY(object_ptr); - if (IS_UNUSED == IS_UNUSED) { - value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(value); - } - variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); - if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); +assign_dim_op_new_array: + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); - goto assign_dim_error; - } else if (IS_VAR == IS_CV) { - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - } else if (IS_VAR == IS_VAR) { - zval *free_op_data = EX_VAR((opline+1)->op1.var); - if (value != free_op_data) { - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - zval_ptr_dtor_nogc(free_op_data); - } - } else if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } + goto assign_dim_op_ret_null; } } else { - dim = NULL; - if (IS_UNUSED == IS_CONST) { - variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + if (IS_CV == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); } else { - variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); } - if (UNEXPECTED(variable_ptr == NULL)) { - goto assign_dim_error; + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; } - value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { - if (EXPECTED(Z_ISREF_P(object_ptr))) { - object_ptr = Z_REFVAL_P(object_ptr); - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { - goto try_assign_dim_array; + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; } } - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if (IS_UNUSED == IS_UNUSED) { - zend_use_new_element_for_string(); - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - } else { - dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); - zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; } - } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_ISREF_P(orig_object_ptr) - && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) - && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = NULL; - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); - goto try_assign_dim_array; + zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } + ZVAL_ARR(container, zend_new_array(8)); + goto assign_dim_op_new_array; } else { - zend_use_scalar_as_array(); - dim = NULL; -assign_dim_error: - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } } - if (IS_UNUSED != IS_UNUSED) { - } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; + zval *var_ptr; zval *value; - zval *variable_ptr; - zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { -try_assign_dim_array: - SEPARATE_ARRAY(object_ptr); - if (IS_UNUSED == IS_UNUSED) { - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(value); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); - if (UNEXPECTED(variable_ptr == NULL)) { + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); - zend_cannot_add_element(); - goto assign_dim_error; - } else if (IS_CV == IS_CV) { - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - } else if (IS_CV == IS_VAR) { - zval *free_op_data = EX_VAR((opline+1)->op1.var); - if (value != free_op_data) { - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - zval_ptr_dtor_nogc(free_op_data); - } - } else if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_REFCOUNTED_P(value))) { - Z_ADDREF_P(value); - } - } - } else { - dim = NULL; - if (IS_UNUSED == IS_CONST) { - variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); - } else { - variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; } - if (UNEXPECTED(variable_ptr == NULL)) { - goto assign_dim_error; + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } } - } else { - if (EXPECTED(Z_ISREF_P(object_ptr))) { - object_ptr = Z_REFVAL_P(object_ptr); - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { - goto try_assign_dim_array; + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + if (IS_CV == IS_CONST) { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + } else { + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); + } + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); } - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if (IS_UNUSED == IS_UNUSED) { - zend_use_new_element_for_string(); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; - UNDEF_RESULT(); - } else { - dim = NULL; - value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; } - } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_ISREF_P(orig_object_ptr) - && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) - && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = NULL; - - UNDEF_RESULT(); - } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); - goto try_assign_dim_array; + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - } else { - zend_use_scalar_as_array(); - dim = NULL; -assign_dim_error: + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + if (IS_CV == IS_CONST) { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + } else { + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); + } + + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); } - } - if (IS_UNUSED != IS_UNUSED) { + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); - } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_dim has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; - zend_class_entry *ce; - uint32_t call_info; - zend_function *fbc; - zend_execute_data *call; + zval *container; SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); - if (IS_VAR == IS_CONST) { - /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); - if (UNEXPECTED(ce == NULL)) { - ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); - if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - - HANDLE_EXCEPTION(); - } - if (IS_UNUSED != IS_CONST) { - CACHE_PTR(opline->result.num, ce); - } - } - } else if (IS_VAR == IS_UNUSED) { - ce = zend_fetch_class(NULL, opline->op1.num); - if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - - HANDLE_EXCEPTION(); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - if (IS_VAR == IS_CONST && - IS_UNUSED == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { - /* nothing to do */ - } else if (IS_VAR != IS_CONST && - IS_UNUSED == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); - } else if (IS_UNUSED != IS_UNUSED) { - function_name = NULL; - if (IS_UNUSED != IS_CONST) { - if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - do { - if (IS_UNUSED & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { - function_name = Z_REFVAL_P(function_name); - if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { - break; - } - } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - } - zend_throw_error(NULL, "Method name must be a string"); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; - HANDLE_EXCEPTION(); - } while (0); - } - } + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_RW(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); - if (ce->get_static_method) { - fbc = ce->get_static_method(ce, Z_STR_P(function_name)); - } else { - fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); - } - if (UNEXPECTED(fbc == NULL)) { - if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); - } + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - HANDLE_EXCEPTION(); - } - if (IS_UNUSED == IS_CONST && - EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); - } - if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { - init_func_run_time_cache(&fbc->op_array); - } - if (IS_UNUSED != IS_CONST) { +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif - } + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - if (UNEXPECTED(ce->constructor == NULL)) { - zend_throw_error(NULL, "Cannot call constructor"); - HANDLE_EXCEPTION(); - } - if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); - HANDLE_EXCEPTION(); - } - fbc = ce->constructor; - if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { - init_func_run_time_cache(&fbc->op_array); + if (IS_CV == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } +} - if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - ce = (zend_class_entry*)Z_OBJ(EX(This)); - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; - } else { - zend_non_static_method_call(fbc); - HANDLE_EXCEPTION(); - } - } else { - /* previous opcode is ZEND_FETCH_CLASS */ - if (IS_VAR == IS_UNUSED - && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { - if (Z_TYPE(EX(This)) == IS_OBJECT) { - ce = Z_OBJCE(EX(This)); - } else { - ce = Z_CE(EX(This)); - } - } - call_info = ZEND_CALL_NESTED_FUNCTION; - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; - call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, ce); - call->prev_execute_data = EX(call); - EX(call) = call; + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); - ZEND_VM_NEXT_OPCODE(); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *property, *container, *result; - if (IS_VAR == IS_UNUSED) { - SAVE_OPLINE(); - zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); - HANDLE_EXCEPTION(); - } else { -/* prevents "undefined variable opline" errors */ -#if 0 || (IS_VAR != IS_UNUSED) - zval *retval_ref, *retval_ptr; - zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - retval_ref = retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + SAVE_OPLINE(); - if (IS_VAR == IS_CONST) { - ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); - retval_ref = retval_ptr = EX_VAR(opline->result.var); - } else if (IS_VAR == IS_VAR) { - if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { - retval_ptr = Z_INDIRECT_P(retval_ptr); - } - ZVAL_DEREF(retval_ptr); - } else if (IS_VAR == IS_CV) { - ZVAL_DEREF(retval_ptr); - } + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_VAR, property, IS_CV, + ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { - ZEND_VM_NEXT_OPCODE(); - } + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - zend_reference *ref = NULL; - void *cache_slot = CACHE_ADDR(opline->op2.num); - if (UNEXPECTED(retval_ref != retval_ptr)) { - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - ref = Z_REF_P(retval_ref); - } else { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); - } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); - } - retval_ptr = retval_ref; - } - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; - SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { - zend_verify_return_error(EX(func), cache_slot, retval_ptr); - HANDLE_EXCEPTION(); - } - ZEND_VM_NEXT_OPCODE(); -#endif + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 USE_OPLINE - zval *result; - zend_function *constructor; - zend_class_entry *ce; - zend_execute_data *call; +#endif - SAVE_OPLINE(); - if (IS_VAR == IS_CONST) { - ce = CACHED_PTR(opline->op2.num); - if (UNEXPECTED(ce == NULL)) { - ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); - if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - CACHE_PTR(opline->op2.num, ce); - } - } else if (IS_VAR == IS_UNUSED) { - ce = zend_fetch_class(NULL, opline->op1.num); - if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) { - ZVAL_UNDEF(result); - HANDLE_EXCEPTION(); + zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); - if (constructor == NULL) { - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim; - /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next - * opcode is DO_FCALL in case EXT instructions are used. */ - if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) { - ZEND_VM_NEXT_OPCODE_EX(1, 2); - } + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = EX_VAR(opline->op2.var); - /* Perform a dummy function call */ - call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL); + if (IS_VAR == IS_VAR + && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT + && UNEXPECTED(!Z_ISREF_P(container)) + ) { + zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); + zend_fetch_dimension_address_LIST_r(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); } else { - if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { - init_func_run_time_cache(&constructor->op_array); - } - /* We are not handling overloaded classes right now */ - call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS, - constructor, - opline->extended_value, - Z_OBJ_P(result)); - Z_ADDREF_P(result); + zend_fetch_dimension_address_W(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); } - call->prev_execute_data = EX(call); - EX(call) = call; - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && - UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (Z_ISREF_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } else { - ZVAL_MAKE_REF_EX(expr_ptr, 2); - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_TMP_VAR) { - /* pass */ - } else if (IS_VAR == IS_CONST) { - Z_TRY_ADDREF_P(expr_ptr); - } else if (IS_VAR == IS_CV) { - ZVAL_DEREF(expr_ptr); - Z_TRY_ADDREF_P(expr_ptr); - } else /* if (IS_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { - zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); - expr_ptr = Z_REFVAL_P(expr_ptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } - } + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } - if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; - zend_string *str; - zend_ulong hval; +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; -add_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_UNUSED != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; + + if (IS_CONST == IS_CONST) { + orig_type = Z_TYPE_P(value); + } + + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_CONST == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); + } + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { - offset = Z_REFVAL_P(offset); - goto add_again; - } else if (Z_TYPE_P(offset) == IS_NULL) { - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else if (Z_TYPE_P(offset) == IS_DOUBLE) { - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - } else if (Z_TYPE_P(offset) == IS_FALSE) { - hval = 0; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_TRUE) { - hval = 1; - goto num_index; - } else if (Z_TYPE_P(offset) == IS_RESOURCE) { - zend_use_resource_as_offset(offset); - hval = Z_RES_HANDLE_P(offset); - goto num_index; - } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { - ZVAL_UNDEFINED_OP2(); - str = ZSTR_EMPTY_ALLOC(); - goto str_index; } else { - zend_illegal_offset(); - zval_ptr_dtor_nogc(expr_ptr); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } } + } - } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { - zend_cannot_add_element(); - zval_ptr_dtor_nogc(expr_ptr); - } + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zval *array; - uint32_t size; - USE_OPLINE + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { - array = EX_VAR(opline->result.var); - if (IS_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - ZVAL_ARR(array, zend_new_array(size)); - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + UNDEF_RESULT(); + goto exit_assign_obj; } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); } -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - var_ptr = EX_VAR(opline->op1.var); - if (UNEXPECTED(Z_ISREF_P(var_ptr))) { - if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { - ZVAL_UNREF(var_ptr); - } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } - ZEND_VM_NEXT_OPCODE(); +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + +exit_assign_obj: + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; - /* Set the new yielded value */ - if (IS_VAR != IS_UNUSED) { - if (UNEXPECTED(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_TMP_VAR)) { - zval *value; + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; - value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); + if (IS_TMP_VAR == IS_CONST) { + orig_type = Z_TYPE_P(value); } - } - } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_VAR == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_TMP_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + goto exit_assign_obj; + } } } else { - zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; + } + } - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + goto exit_assign_obj; } } - } 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; - if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { - key = Z_REFVAL_P(key); - } - ZVAL_COPY(&generator->key, 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 (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(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); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); } else { - generator->send_target = NULL; + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } } - /* 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 ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1 = EX_VAR(opline->op1.var); + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - if (IS_VAR == IS_CV) { - if (UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_NEW_EMPTY_REF(op1); - Z_SET_REFCOUNT_P(op1, 2); - ZVAL_NULL(Z_REFVAL_P(op1)); - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); - } else { - if (Z_ISREF_P(op1)) { - Z_ADDREF_P(op1); - } else { - ZVAL_MAKE_REF_EX(op1, 2); - } - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); - } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) { - op1 = Z_INDIRECT_P(op1); - if (EXPECTED(!Z_ISREF_P(op1))) { - ZVAL_MAKE_REF_EX(op1, 2); - } else { - GC_ADDREF(Z_REF_P(op1)); - } - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); - } else { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1; - zend_string *type; - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - type = zend_zval_get_type(op1); - if (EXPECTED(type)) { - ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); - } else { - ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - zval *value, *container, *dim; + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { -assign_dim_op_array: - SEPARATE_ARRAY(container); -assign_dim_op_new_array: - dim = EX_VAR(opline->op2.var); - if (IS_CV == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); - if (UNEXPECTED(!var_ptr)) { - zend_cannot_add_element(); - goto assign_dim_op_ret_null; - } - } else { - if (IS_CV == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); - } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); - } - if (UNEXPECTED(!var_ptr)) { - goto assign_dim_op_ret_null; - } + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; - do { - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - } - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - } else { - if (EXPECTED(Z_ISREF_P(container))) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto assign_dim_op_array; - } - } + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CONST) { + orig_type = Z_TYPE_P(value); + } - if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); - } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_VAR == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); + } + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } } - ZVAL_ARR(container, zend_new_array(8)); - goto assign_dim_op_new_array; } else { - zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); -assign_dim_op_ret_null: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; + } } - } - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_EX(1, 2); -} + if (!zobj->ce->__set) { -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; - zval *value; + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } - SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; + zval *object, *property, *value, tmp; zend_object *zobj; zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - do { - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto post_incdec_object; - } - if (IS_VAR == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; - } - -post_incdec_object: - /* here we are sure we are dealing with an object */ - zobj = Z_OBJ_P(object); - if (IS_CV == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - break; - } + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; } - cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - if (IS_CV == IS_CONST) { - prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } - zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); - } - } else { - zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); - } - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - } while (0); +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST && + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(object); + zval *property_val; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_CONST) { + orig_type = Z_TYPE_P(value); + } - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; + /* will remain valid, thus no need to check prop_info in future here */ + if (IS_CV == IS_CONST && Z_TYPE_P(value) == orig_type) { + CACHE_PTR_EX(cache_slot + 2, NULL); + } + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1); + if (property_val) { + goto fast_assign_obj; + } + } - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_RW(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + if (!zobj->ce->__set) { - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); } else { - if (IS_CV == IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *property, *result; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - result = EX_VAR(opline->result.var); - zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *dim; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - dim = EX_VAR(opline->op2.var); - if (IS_VAR == IS_VAR - && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT - && UNEXPECTED(!Z_ISREF_P(container)) - ) { - zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); - zend_fetch_dimension_address_LIST_r(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_fetch_dimension_address_W(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); - } +exit_assign_obj: - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -28335,6 +28312,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_VAR == IS_UNUSED) { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_VAR == IS_UNUSED) { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -29482,7 +29533,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_ ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -29499,7 +29550,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -29624,7 +29675,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if (IS_UNUSED == IS_CONST) { + if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -31349,7 +31400,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -31366,7 +31417,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVA result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -31491,7 +31542,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if (IS_UNUSED == IS_CONST) { + if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -33744,7 +33795,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HAN ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -33761,7 +33812,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HA result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -33886,7 +33937,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if (IS_UNUSED == IS_CONST) { + if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -38056,7 +38107,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HAND ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -38073,7 +38124,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HAN result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -38198,7 +38249,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CON if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if (IS_CV == IS_CONST) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -41534,7 +41585,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HAN (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -41551,7 +41602,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HA result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -41676,7 +41727,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if (IS_CV == IS_CONST) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -46342,7 +46393,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -46359,7 +46410,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLE result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -46484,7 +46535,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_ if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if (IS_CV == IS_CONST) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -49444,56 +49495,56 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_LABEL, (void*)&&ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST_LABEL, (void*)&&ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP_LABEL, (void*)&&ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR_LABEL, @@ -49604,16 +49655,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_LABEL, (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONST_LABEL, (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_LABEL, (void*)&&ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_LABEL, @@ -49682,19 +49733,13 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -49702,34 +49747,40 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_VAR_LABEL, @@ -50144,16 +50195,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST_LABEL, - (void*)&&ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV_LABEL, - (void*)&&ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST_LABEL, - (void*)&&ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_FETCH_OBJ_W_SPEC_VAR_CV_LABEL, (void*)&&ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_LABEL, (void*)&&ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_LABEL, (void*)&&ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_LABEL, @@ -50199,16 +50250,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST_LABEL, - (void*)&&ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV_LABEL, - (void*)&&ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST_LABEL, - (void*)&&ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_LABEL, (void*)&&ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_LABEL, (void*)&&ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_LABEL, (void*)&&ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_LABEL, @@ -50309,16 +50360,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_LABEL, - (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST_LABEL, - (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_LABEL, + (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_LABEL, + (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_LABEL, + (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV_LABEL, - (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST_LABEL, - (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_LABEL, + (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_LABEL, + (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV_LABEL, + (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_LABEL, (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_LABEL, (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_LABEL, (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_LABEL, @@ -50584,16 +50635,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST_LABEL, - (void*)&&ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV_LABEL, - (void*)&&ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST_LABEL, - (void*)&&ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_PRE_INC_OBJ_SPEC_VAR_CV_LABEL, (void*)&&ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_LABEL, (void*)&&ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_LABEL, (void*)&&ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_LABEL, @@ -53421,14 +53472,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_BOOL_XOR_SPEC_TMPVAR_CONST) ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST): - VM_TRACE(ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST) - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST): - VM_TRACE(ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST) - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST): VM_TRACE(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST) ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53441,46 +53484,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST) ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST): - VM_TRACE(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST) - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST): - VM_TRACE(ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST) - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST): VM_TRACE(ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST) ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST): - VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST) - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR): - VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR) - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV): - VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV) - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST): VM_TRACE(ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST) ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53561,14 +53568,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR) ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR): - VM_TRACE(ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR) - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR): - VM_TRACE(ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR) - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR): VM_TRACE(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR) ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53581,46 +53580,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR) ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR): - VM_TRACE(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR) - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR): - VM_TRACE(ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR) - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR): VM_TRACE(ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR) ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR): - VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR) - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR): - VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV): - VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR): VM_TRACE(ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR) ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53713,14 +53676,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_SPACESHIP_SPEC_TMPVAR_CV) ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV): - VM_TRACE(ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV) - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV): - VM_TRACE(ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV) - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV): VM_TRACE(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV) ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53733,46 +53688,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV) ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV): - VM_TRACE(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV) - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV): - VM_TRACE(ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV) - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV): VM_TRACE(ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV) ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV): - VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV) - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV): - VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV) - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR): - VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR) - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV): - VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV) - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_FAST_CONCAT_SPEC_TMPVAR_CV): VM_TRACE(ZEND_FAST_CONCAT_SPEC_TMPVAR_CV) ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53930,6 +53849,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST) ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST): + VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST) + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ROPE_ADD_SPEC_TMP_CONST): VM_TRACE(ZEND_ROPE_ADD_SPEC_TMP_CONST) ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53958,6 +53881,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR) ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR): + VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR) + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ROPE_ADD_SPEC_TMP_TMPVAR): VM_TRACE(ZEND_ROPE_ADD_SPEC_TMP_TMPVAR) ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54014,6 +53941,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV) ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV): + VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV) + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ROPE_ADD_SPEC_TMP_CV): VM_TRACE(ZEND_ROPE_ADD_SPEC_TMP_CV) ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54227,6 +54158,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST) ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST): + VM_TRACE(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST) + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST): VM_TRACE(ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST) ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54235,6 +54170,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_OP_SPEC_VAR_CONST) ZEND_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_PRE_INC_OBJ_SPEC_VAR_CONST): + VM_TRACE(ZEND_PRE_INC_OBJ_SPEC_VAR_CONST) + ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_POST_INC_OBJ_SPEC_VAR_CONST): VM_TRACE(ZEND_POST_INC_OBJ_SPEC_VAR_CONST) ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54255,6 +54194,18 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST) ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_W_SPEC_VAR_CONST): + VM_TRACE(ZEND_FETCH_OBJ_W_SPEC_VAR_CONST) + ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST): + VM_TRACE(ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST) + ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST): + VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST) + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST): VM_TRACE(ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST) ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54263,6 +54214,22 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_LIST_W_SPEC_VAR_CONST) ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST) + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP) + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR) + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV) + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST): VM_TRACE(ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST) ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54287,6 +54254,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED) ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR): + VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR) + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV): + VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV) + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST): VM_TRACE(ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST) ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54319,6 +54294,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_IN_ARRAY_SPEC_VAR_CONST) ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR): + VM_TRACE(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR) + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR): VM_TRACE(ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR) ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54327,6 +54306,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR) ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR): + VM_TRACE(ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR) + ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR): VM_TRACE(ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR) ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54347,6 +54330,18 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR) ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR): + VM_TRACE(ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR) + ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR): + VM_TRACE(ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR) + ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR): + VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR) + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR): VM_TRACE(ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR) ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54355,6 +54350,22 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR) ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST) + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP) + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR) + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV) + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST): VM_TRACE(ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST) ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54371,6 +54382,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV) ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR): + VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR) + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV): + VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV) + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR): VM_TRACE(ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR) ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54499,6 +54518,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_GET_TYPE_SPEC_VAR_UNUSED) ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV): + VM_TRACE(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV) + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV): VM_TRACE(ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV) ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54507,6 +54530,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_OP_SPEC_VAR_CV) ZEND_ASSIGN_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_PRE_INC_OBJ_SPEC_VAR_CV): + VM_TRACE(ZEND_PRE_INC_OBJ_SPEC_VAR_CV) + ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_POST_INC_OBJ_SPEC_VAR_CV): VM_TRACE(ZEND_POST_INC_OBJ_SPEC_VAR_CV) ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54527,6 +54554,18 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV) ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_W_SPEC_VAR_CV): + VM_TRACE(ZEND_FETCH_OBJ_W_SPEC_VAR_CV) + ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_RW_SPEC_VAR_CV): + VM_TRACE(ZEND_FETCH_OBJ_RW_SPEC_VAR_CV) + ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV): + VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV) + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV): VM_TRACE(ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV) ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54535,6 +54574,22 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_LIST_W_SPEC_VAR_CV) ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST) + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP) + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR) + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV): + VM_TRACE(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV) + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST): VM_TRACE(ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST) ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54563,6 +54618,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_REF_SPEC_VAR_CV) ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR): + VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR) + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV): + VM_TRACE(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV) + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV): VM_TRACE(ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV) ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56976,56 +57039,56 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_HANDLER, ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST_HANDLER, ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP_HANDLER, ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER, @@ -57136,16 +57199,16 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST_HANDLER, - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV_HANDLER, - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST_HANDLER, - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HANDLER, ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONST_HANDLER, ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_HANDLER, @@ -57214,19 +57277,13 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -57234,34 +57291,40 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER, @@ -57676,16 +57739,16 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_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_TMPVAR_HANDLER, ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER, @@ -57731,16 +57794,16 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_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_TMPVAR_HANDLER, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER, @@ -57841,16 +57904,16 @@ void zend_vm_init(void) 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_TMPVAR_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_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_TMPVAR_CV_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_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_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV_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_TMPVAR_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER, @@ -58116,16 +58179,16 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_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_TMPVAR_HANDLER, ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 870506e8e2..e5d50a4083 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -436,38 +436,22 @@ _(857, ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_TMP) \ _(858, ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_VAR) \ _(860, ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CV) \ - _(886, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST) \ - _(887, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP) \ - _(888, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR) \ - _(890, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV) \ - _(891, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST) \ - _(892, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP) \ - _(893, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) \ - _(895, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) \ - _(896, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST) \ - _(897, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP) \ - _(898, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) \ - _(900, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) \ - _(906, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST) \ - _(907, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP) \ - _(908, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR) \ - _(910, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV) \ - _(911, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST) \ - _(912, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP) \ - _(913, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR) \ - _(915, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV) \ - _(916, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST) \ - _(917, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP) \ - _(918, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) \ - _(920, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) \ - _(921, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST) \ - _(922, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP) \ - _(923, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) \ - _(925, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) \ - _(931, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST) \ - _(932, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP) \ - _(933, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR) \ - _(935, ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV) \ + _(911, ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST) \ + _(912, ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP) \ + _(913, ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR) \ + _(915, ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV) \ + _(916, ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST) \ + _(917, ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP) \ + _(918, ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR) \ + _(920, ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV) \ + _(921, ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST) \ + _(922, ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP) \ + _(923, ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR) \ + _(925, ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV) \ + _(931, ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST) \ + _(932, ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP) \ + _(933, ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR) \ + _(935, ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV) \ _(936, ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST) \ _(937, ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP) \ _(938, ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR) \ @@ -522,14 +506,10 @@ _(1038, ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR) \ _(1039, ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED) \ _(1040, ZEND_ASSIGN_DIM_OP_SPEC_CV_CV) \ - _(1046, ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST) \ - _(1047, ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR) \ - _(1048, ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR) \ - _(1050, ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV) \ - _(1051, ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST) \ - _(1052, ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR) \ - _(1053, ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR) \ - _(1055, ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV) \ + _(1051, ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST) \ + _(1052, ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR) \ + _(1053, ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR) \ + _(1055, ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV) \ _(1056, ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONST) \ _(1057, ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR) \ _(1058, ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR) \ @@ -547,22 +527,14 @@ _(1093, ZEND_QM_ASSIGN_SPEC_TMP) \ _(1094, ZEND_QM_ASSIGN_SPEC_VAR) \ _(1096, ZEND_QM_ASSIGN_SPEC_CV) \ - _(1124, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR) \ - _(1126, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV) \ - _(1129, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) \ - _(1131, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) \ - _(1134, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) \ - _(1136, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) \ - _(1144, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR) \ - _(1146, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV) \ - _(1149, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR) \ - _(1151, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV) \ - _(1154, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) \ - _(1156, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) \ - _(1159, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) \ - _(1161, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) \ - _(1169, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR) \ - _(1171, ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV) \ + _(1149, ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR) \ + _(1151, ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV) \ + _(1154, ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR) \ + _(1156, ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV) \ + _(1159, ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR) \ + _(1161, ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV) \ + _(1169, ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR) \ + _(1171, ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV) \ _(1174, ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_VAR) \ _(1176, ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_CV) \ _(1179, ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_VAR) \ @@ -817,14 +789,10 @@ _(1578, ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR) \ _(1579, ZEND_FETCH_DIM_W_SPEC_CV_UNUSED) \ _(1580, ZEND_FETCH_DIM_W_SPEC_CV_CV) \ - _(1586, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST) \ - _(1587, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR) \ - _(1588, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR) \ - _(1590, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV) \ - _(1591, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST) \ - _(1592, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR) \ - _(1593, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR) \ - _(1595, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV) \ + _(1591, ZEND_FETCH_OBJ_W_SPEC_VAR_CONST) \ + _(1592, ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR) \ + _(1593, ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR) \ + _(1595, ZEND_FETCH_OBJ_W_SPEC_VAR_CV) \ _(1596, ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST) \ _(1597, ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR) \ _(1598, ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR) \ @@ -847,14 +815,10 @@ _(1633, ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR) \ _(1634, ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED) \ _(1635, ZEND_FETCH_DIM_RW_SPEC_CV_CV) \ - _(1641, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST) \ - _(1642, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR) \ - _(1643, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR) \ - _(1645, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV) \ - _(1646, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST) \ - _(1647, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR) \ - _(1648, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR) \ - _(1650, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV) \ + _(1646, ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST) \ + _(1647, ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR) \ + _(1648, ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR) \ + _(1650, ZEND_FETCH_OBJ_RW_SPEC_VAR_CV) \ _(1651, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST) \ _(1652, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR) \ _(1653, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR) \ @@ -931,14 +895,14 @@ _(1747, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR) \ _(1748, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR) \ _(1750, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV) \ - _(1751, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST) \ - _(1752, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR) \ - _(1753, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR) \ - _(1755, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV) \ - _(1756, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST) \ - _(1757, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR) \ - _(1758, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR) \ - _(1760, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV) \ + _(1751, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST) \ + _(1752, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR) \ + _(1753, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR) \ + _(1755, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV) \ + _(1756, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST) \ + _(1757, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR) \ + _(1758, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR) \ + _(1760, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV) \ _(1761, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST) \ _(1762, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR) \ _(1763, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR) \ @@ -1115,14 +1079,10 @@ _(2018, ZEND_DO_UCALL_SPEC_RETVAL_USED) \ _(2019, ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED) \ _(2020, ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED) \ - _(2026, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST) \ - _(2027, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR) \ - _(2028, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR) \ - _(2030, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV) \ - _(2031, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST) \ - _(2032, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR) \ - _(2033, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR) \ - _(2035, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV) \ + _(2031, ZEND_PRE_INC_OBJ_SPEC_VAR_CONST) \ + _(2032, ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR) \ + _(2033, ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR) \ + _(2035, ZEND_PRE_INC_OBJ_SPEC_VAR_CV) \ _(2036, ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST) \ _(2037, ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR) \ _(2038, ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR) \ diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 143bac1960..65733779e4 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -245,15 +245,15 @@ static uint32_t zend_vm_opcodes_flags[195] = { 0x00000b0b, 0x00000301, 0x00006701, - 0x00040755, + 0x00040751, 0x00040000, 0x04000701, 0x04006701, - 0x04000755, + 0x04000751, 0x04000000, 0x0b000101, 0x00000003, - 0x0b040755, + 0x0b040751, 0x0b040000, 0x00000001, 0x00000001, @@ -306,16 +306,16 @@ static uint32_t zend_vm_opcodes_flags[195] = { 0x00040757, 0x00010107, 0x00006701, - 0x00640755, + 0x00640751, 0x00010107, 0x00006701, - 0x00040755, + 0x00040751, 0x00010107, 0x00000707, 0x00040757, 0x00010107, 0x00006703, - 0x00240757, + 0x00240753, 0x00010107, 0x00000701, 0x00040751, @@ -353,7 +353,7 @@ static uint32_t zend_vm_opcodes_flags[195] = { 0x00000000, 0x00000000, 0x00000000, - 0x00040755, + 0x00040751, 0x00040751, 0x00040751, 0x00040751, diff --git a/ext/simplexml/tests/bug35785.phpt b/ext/simplexml/tests/bug35785.phpt index 9ffea71e30..420515bb03 100644 --- a/ext/simplexml/tests/bug35785.phpt +++ b/ext/simplexml/tests/bug35785.phpt @@ -12,9 +12,15 @@ $xml = simplexml_load_string(""); var_dump(isset($xml->bla->posts)); $xml->bla->posts[0]->name = "FooBar"; echo $xml->asXML(); +$xml = simplexml_load_string(""); +$xml->bla->posts[]->name = "FooBar"; +echo $xml->asXML(); ?> ---EXPECTF-- -Fatal error: Uncaught Error: Attempt to assign property 'name' of non-object in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d +--EXPECT-- + +FooBar +bool(false) + +FooBar + +FooBar diff --git a/ext/simplexml/tests/bug41582.phpt b/ext/simplexml/tests/bug41582.phpt index a896530dc3..b270f3b639 100644 --- a/ext/simplexml/tests/bug41582.phpt +++ b/ext/simplexml/tests/bug41582.phpt @@ -13,5 +13,6 @@ $xml->movie[]->characters->character[0]->name = 'Miss Coder'; echo($xml->asXml()); ?> ---EXPECTF-- -Fatal error: Cannot use [] for reading in %s on line %d +--EXPECT-- + +Miss Coder