From: Nikita Popov Date: Tue, 10 Mar 2020 09:50:17 +0000 (+0100) Subject: Fetch for read in nested property assignments X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bb43a3822e42dbd15b1d416a166549d3980b379a;p=php Fetch for read in nested property assignments $a->b->c = 'd'; is now compiled the same way as $b = $a->b; $b->c = 'd'; That is, we perform a read fetch on $a->b, rather than a write fetch. This is possible, because PHP 8 removed auto-vivification support for objects, so $a->b->c = 'd' may no longer modify $a->b proper (i.e. not counting interior mutability of the object). Closes GH-5250. --- diff --git a/UPGRADING b/UPGRADING index 787bc08663..ac35b36c6c 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,6 +305,19 @@ 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 652db2de20..31e7af42cd 100644 --- a/Zend/tests/033.phpt +++ b/Zend/tests/033.phpt @@ -15,14 +15,6 @@ 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 @@ -62,5 +54,16 @@ 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 af73344f5d..b14e400d44 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: Cannot use string offset as an object in %s:%d +Fatal error: Uncaught Error: Attempt to assign property 'bar' of non-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 2af13acdc9..15bd399b78 100644 --- a/Zend/tests/bug41919.phpt +++ b/Zend/tests/bug41919.phpt @@ -8,7 +8,9 @@ $foo[3]->bar[1] = "bang"; echo "ok\n"; ?> --EXPECTF-- -Fatal error: Uncaught Error: Cannot use string offset as an object in %sbug41919.php:%d +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 Stack trace: #0 {main} thrown in %sbug41919.php on line %d diff --git a/Zend/tests/bug47704.phpt b/Zend/tests/bug47704.phpt index 4fdaba8092..5375dbc339 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: Cannot use string offset as an object in %sbug47704.php:%d +Fatal error: Uncaught Error: Attempt to assign property 'a' of non-object in %s:%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 e5aca5c82e..ab37203dcd 100644 --- a/Zend/tests/bug52041.phpt +++ b/Zend/tests/bug52041.phpt @@ -51,19 +51,25 @@ 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 -Attempt to modify property 'a' of non-object + +Warning: Trying to get property 'a' of non-object in %s on line %d +Attempt to assign property 'b' 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 -Attempt to modify property 'a' of non-object + +Warning: Trying to get property 'a' of non-object in %s on line %d +Attempt to increment/decrement property 'b' 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 -Attempt to modify property 'a' of non-object + +Warning: Trying to get property 'a' of non-object in %s on line %d +Attempt to assign property 'b' 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 a8649262b5..11bab4b4ce 100644 --- a/Zend/tests/bug75921.phpt +++ b/Zend/tests/bug75921.phpt @@ -53,15 +53,29 @@ Attempt to modify property 'a' of non-object Warning: Undefined variable: null in %s on line %d NULL -Attempt to modify property 'a' of non-object + +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 Warning: Undefined variable: null in %s on line %d NULL -Attempt to modify property 'a' of non-object + +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 Warning: Undefined variable: null in %s on line %d NULL -Attempt to modify property 'a' of non-object + +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 Warning: Undefined variable: null in %s on line %d NULL diff --git a/Zend/tests/bug78531.phpt b/Zend/tests/bug78531.phpt index 1e8f0b34d1..a8850fb8c2 100644 --- a/Zend/tests/bug78531.phpt +++ b/Zend/tests/bug78531.phpt @@ -34,4 +34,6 @@ 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 -Attempt to modify property 'a' of non-object + +Warning: Trying to get property 'a' of non-object in %s on line %d +Attempt to assign property 'a' of non-object diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2050e3ba71..9fa1f20f2d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2703,7 +2703,13 @@ 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 { - opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0); + /* 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); + } 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 68ef127ef6..43b64cde62 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, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP) +ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP) { USE_OPLINE zval *object; @@ -1002,7 +1002,7 @@ ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP) zend_string *name, *tmp_name; SAVE_OPLINE(); - object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); + object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); 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_VAR_PTR(); + FREE_OP1(); /* 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, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) +ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE zval *object; @@ -1260,7 +1260,7 @@ ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH zend_string *name, *tmp_name; SAVE_OPLINE(); - object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); + object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); 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_VAR_PTR(); + FREE_OP1(); 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_PTR_UNDEF(BP_VAR_RW); + object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); 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_VAR_PTR(); + FREE_OP1(); 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, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_WRITE|CACHE_SLOT) +ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, TMPVAR|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_PTR_UNDEF(BP_VAR_W); + container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); 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, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH ((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) { + if (OP1_TYPE & (IS_VAR|IS_TMP_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, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) +ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE zval *property, *container, *result; SAVE_OPLINE(); - container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); + container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); 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) { + if (OP1_TYPE & (IS_VAR|IS_TMP_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|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|CACHE_SLOT) +ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMPVAR|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|TMP|VAR|UNUSED|THI if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { /* Behave like FETCH_OBJ_W */ - if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { + if (OP1_TYPE == IS_CONST) { 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, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV)) +ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, TMPVAR|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, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_ zend_string *name, *tmp_name; SAVE_OPLINE(); - object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); + object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); 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_VAR_PTR(); + FREE_OP1(); /* 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, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT|SRC, SPEC(OP_DATA=VAR|CV)) +ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, TMPVAR|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_PTR_UNDEF(BP_VAR_W); + container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); 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, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CA zend_assign_to_property_reference(container, OP1_TYPE, property, OP2_TYPE, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - FREE_OP1_VAR_PTR(); + FREE_OP1(); 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 f7155da46f..683db7cf82 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|IS_TMP_VAR))) { + if (IS_CONST == IS_CONST) { 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|IS_TMP_VAR))) { + if (IS_CONST == IS_CONST) { 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|IS_TMP_VAR))) { + if (IS_CONST == IS_CONST) { 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,6 +13897,170 @@ 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 @@ -14066,6 +14230,44 @@ 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 @@ -14177,676 +14379,694 @@ fetch_obj_is_finish: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -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_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 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); - 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(); - } +#endif - 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(); + 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_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)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - } - op2_str = zval_get_string_func(op2); + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - 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_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST_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; + 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); + value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (IS_CONST != IS_CONST) { - function_name = RT_CONSTANT(opline, opline->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; + } + 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 && - 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; +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 (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(); + } + } 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; } } - zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } while (0); - } + if (!zobj->ce->__set) { - 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 (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); } - 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) { - + 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); } - HANDLE_EXCEPTION(); + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); } } - if (IS_CONST == IS_CONST) { - function_name = RT_CONSTANT(opline, opline->op2); + 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); } - zend_invalid_method_call(object, function_name); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); + goto exit_assign_obj; } - } while (0); + } } - obj = Z_OBJ_P(object); - called_scope = obj->ce; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } - if (IS_CONST == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); } else { - zend_object *orig_obj = obj; - - if (IS_CONST == IS_CONST) { - function_name = RT_CONSTANT(opline, opline->op2); - } - - /* 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)); - } + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!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); + 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); + } +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - 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)); +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; - } - - 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(); + 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_CASE_SPEC_TMPVAR_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_TMPVAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - double d1, d2; + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; - 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)); + 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); - if (result) { - goto case_true; - } else { - goto case_false; - } + 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; } - 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_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - int result; - zend_ulong hval; - zval *offset; +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; - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = RT_CONSTANT(opline, opline->op2); + 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 (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; - zval *value; - zend_string *str; + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; -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; + 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; } } - 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 (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 (!(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 */ + if (!zobj->ce->__set) { - ZEND_VM_SMART_BRANCH(result, 0); + 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 { - 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 (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); } - if (!(opline->extended_value & ZEND_ISEMPTY)) { - result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); } else { - result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + 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; + } } -isset_dim_obj_exit: + 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); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_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_TMPVAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - int result; - zval *offset; + zval *object, *property, *value, tmp; + zend_object *zobj; zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = RT_CONSTANT(opline, opline->op2); + 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_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; + 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); + + /* 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; + } } } else { - result = (opline->extended_value & ZEND_ISEMPTY); - goto isset_object_finish; + 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_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + if (IS_CONST == IS_CONST) { - name = Z_STR_P(offset); + name = Z_STR_P(property); } else { - name = zval_try_get_tmp_string(offset, &tmp_name); + name = zval_try_get_tmp_string(property, &tmp_name); if (UNEXPECTED(!name)) { - result = 0; - goto isset_object_finish; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; } } - 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)); + 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); } -isset_object_finish: +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_SMART_BRANCH(result, 1); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_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_TMPVAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *key, *subject; - HashTable *ht; - zend_bool result; + 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); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - 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; - } + 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_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); - result = 0; + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} +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; -/* 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 (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); - SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; -try_instanceof: - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; + if (IS_CV == IS_CONST) { + orig_type = Z_TYPE_P(value); + } - 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); + 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); + } + 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 (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 (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; + } + } -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 (!zobj->ce->__set) { - 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 (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; + } } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); } else { -fetch_dim_r_index_slow: - SAVE_OPLINE(); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; } - 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); + 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: + 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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_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_TMPVAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; - zend_long offset; - HashTable *ht; + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); 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; + 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); + } } else { - goto fetch_dim_r_index_slow; + 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 { -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(); + 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_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(); + + 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_DIV_SPEC_TMPVAR_TMPVAR_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_TMPVAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *property, *container, *value_ptr; 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; + 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); + } - 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(); + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* 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) { USE_OPLINE zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + 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_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == 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_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + 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); @@ -14854,13 +15074,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND 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_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_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + 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 && @@ -14870,7 +15090,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND 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_CONST & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } else { @@ -14881,161 +15101,698 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND 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)) { + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } ZEND_VM_NEXT_OPCODE(); - } else { - SAVE_OPLINE(); + } + 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)) { - op1 = ZVAL_UNDEFINED_OP1(); + ZVAL_UNDEFINED_OP1(); } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { - op2 = ZVAL_UNDEFINED_OP2(); + 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(); } - 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(); + 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_IS_EQUAL_SPEC_TMPVAR_TMPVAR_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 *op1, *op2; - double d1, d2; + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; - 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(); + 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(); + } } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = (double)Z_LVAL_P(op1); - d2 = Z_DVAL_P(op2); - 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); -is_equal_double: - if (d1 == d2) { - goto is_equal_true; - } else { - goto is_equal_false; + 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_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + 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; + } 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(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); + + /* 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 (result) { - 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(); + } + /* 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; } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + + 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_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_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)) { + 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))) { -is_equal_true: - ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); +case_true: + ZEND_VM_SMART_BRANCH_TRUE(); } else { -is_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); +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 is_equal_double; + 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); -is_equal_double: +case_double: if (d1 == d2) { - goto is_equal_true; + goto case_true; } else { - goto is_equal_false; + goto case_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 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_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; + goto case_true; } else { - goto is_equal_false; + goto case_false; } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_case_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_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - double d1, d2; + zval *container; + int result; + zend_ulong hval; + zval *offset; - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + 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) +{ + 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_equal_true: - ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15076,7 +15833,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_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_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; @@ -15088,32 +15845,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA /* 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_NONE(); + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); } else { -is_not_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_NONE(); +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 is_not_equal_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); -is_not_equal_double: - if (d1 != d2) { - goto is_not_equal_true; +is_equal_double: + if (d1 == d2) { + goto is_equal_true; } else { - goto is_not_equal_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 is_not_equal_double; + goto is_equal_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { @@ -15124,17 +15881,17 @@ is_not_equal_double: if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op2); } - if (!result) { - goto is_not_equal_true; + if (result) { + goto is_equal_true; } else { - goto is_not_equal_false; + goto is_equal_false; } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_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_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_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; @@ -15146,32 +15903,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA /* 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(); + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); } else { -is_not_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); +is_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; + 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); -is_not_equal_double: - if (d1 != d2) { - goto is_not_equal_true; +is_equal_double: + if (d1 == d2) { + goto is_equal_true; } else { - goto is_not_equal_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 is_not_equal_double; + goto is_equal_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { @@ -15182,17 +15939,17 @@ is_not_equal_double: if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op2); } - if (!result) { - goto is_not_equal_true; + if (result) { + goto is_equal_true; } else { - goto is_not_equal_false; + goto is_equal_false; } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_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_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_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; @@ -15206,10 +15963,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_JMPNZ(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15250,37 +16007,318 @@ 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_SPACESHIP_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); - compare_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_BOOL_XOR_SPEC_TMPVAR_TMPVAR_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; + double d1, d2; - SAVE_OPLINE(); op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - boolean_xor_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_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + 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(); + 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); + 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_BOOL_XOR_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); + boolean_xor_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_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 zval *container, *dim, *value; SAVE_OPLINE(); @@ -15447,6 +16485,44 @@ 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 @@ -15558,3662 +16634,4053 @@ fetch_obj_is_finish: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -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_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 USE_OPLINE - zval *op1, *op2; - zend_string *op1_str, *op2_str, *str; - - - 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(); - } +#endif - 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(); + 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_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)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } 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); + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - 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_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_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; + 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 = RT_CONSTANT((opline+1), (opline+1)->op1); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.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; } - 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); - } +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 ((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_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.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); + + 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 (!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); } - HANDLE_EXCEPTION(); + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); } } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + 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); } - 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(); + goto exit_assign_obj; } - } while (0); + } } - obj = Z_OBJ_P(object); - called_scope = obj->ce; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); } 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); - } + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { - /* 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); + 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) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zend_tmp_string_release(tmp_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)); - - 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; +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; - - ZEND_VM_NEXT_OPCODE(); +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_CASE_SPEC_TMPVAR_TMPVAR_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_TMPVAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - double d1, d2; + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; - 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; - } + 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); + + 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; } - 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) -{ - USE_OPLINE - zval *container; - int result; - zend_ulong hval; - zval *offset; +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_var(opline->op1.var EXECUTE_DATA_CC); - offset = _get_zval_ptr_var(opline->op2.var 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 (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; - zval *value; - zend_string *str; + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; -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; + 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; } } - 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 { - value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); - if (UNEXPECTED(EG(exception))) { - result = 0; - goto isset_dim_obj_exit; + 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 (!(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 (!zobj->ce->__set) { - 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); + 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 { - 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_VAR) == 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->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) -{ - 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 = _get_zval_ptr_var(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))) { - 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_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(offset); + name = Z_STR_P(property); } else { - name = zval_try_get_tmp_string(offset, &tmp_name); + name = zval_try_get_tmp_string(property, &tmp_name); if (UNEXPECTED(!name)) { - result = 0; - goto isset_object_finish; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; } } - 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)); + 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); } -isset_object_finish: +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_SMART_BRANCH(result, 1); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_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_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *key, *subject; - HashTable *ht; - zend_bool result; + 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_var((opline+1)->op1.var EXECUTE_DATA_CC); - 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; - } + 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_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); - result = 0; + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} +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; -/* 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 (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); - SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; -try_instanceof: - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; + if (IS_VAR == IS_CONST) { + orig_type = Z_TYPE_P(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); + 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; } } - } 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(); + 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 = 0; } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} - -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; - SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } 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; + name = Z_STR_P(property); } 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); + name = zval_try_get_tmp_string(property, &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); - } - } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; } } - if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } + 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); } - 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); +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(); + 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)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_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_TMPVAR_TMPVAR_OP_DATA_CV_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 *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; -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)); -} + 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); -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)); -} + 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; + } -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)); -} +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; -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)); -} + 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_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)); -} + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; -/* 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; + if (IS_CV == IS_CONST) { + orig_type = Z_TYPE_P(value); + } - SAVE_OPLINE(); + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - varname = _get_zval_ptr_var(opline->op1.var 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); + } + 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; + } + } + + 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; + } + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } 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; + name = Z_STR_P(property); } else { - 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); + name = zval_try_get_tmp_string(property, &tmp_name); if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); + + UNDEF_RESULT(); + goto exit_assign_obj; } } - target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); - zend_hash_del_ind(target_symbol_table, name); + 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); + } + +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); } -/* 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) +/* 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) { USE_OPLINE - zval *value; - int result; - zval *varname; - zend_string *name, *tmp_name; - HashTable *target_symbol_table; + zval *property, *container, *value_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 { - name = zval_get_tmp_string(varname, &tmp_name); - } - 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); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - 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 (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); } - result = Z_TYPE_P(value) > IS_NULL; } else { - result = !i_zend_is_true(value); + 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_TMP_VAR|IS_VAR), property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - ZEND_VM_SMART_BRANCH(result, 1); + 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); } -/* 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) +/* 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) { USE_OPLINE - zval *expr; - zend_bool result; + zval *property, *container, *value_ptr; 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; + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var 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_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(); + 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_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 { - ce = Z_CE_P(EX_VAR(opline->op2.var)); + 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); + } } - 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_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_SMART_BRANCH(result, 1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_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_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; - zend_long count; + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + - 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); + 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; - /* 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 ((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 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_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); - /* 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(); + 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); } - count = 0; } else { - count = 1; + 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_error(E_WARNING, "%s(): Parameter must be an array or an object that implements Countable", opline->extended_value ? "sizeof" : "count"); - break; + ZEND_VM_NEXT_OPCODE(); } - ZVAL_LONG(EX_VAR(opline->result.var), count); + 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(); + } + 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_GET_CLASS_SPEC_TMPVAR_UNUSED_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 *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; - 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(); - 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 { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + 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_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_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; - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_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); } -} -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(); -} + 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_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + HANDLE_EXCEPTION(); + } + } + 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); + } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; + obj = Z_OBJ_P(object); + called_scope = obj->ce; - 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)); + 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; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; + /* 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); + } + } - 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)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + 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(); + } + /* 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_CONCAT_SPEC_TMPVAR_CV_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 *op1, *op2; + double d1, d2; 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); + 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 { - 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); +case_false: + ZEND_VM_SMART_BRANCH_FALSE(); } - } 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 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 { - ZVAL_STR(EX_VAR(opline->result.var), op1_str); + goto case_false; } - if (IS_CV & (IS_TMP_VAR|IS_VAR)) { - zend_string_release_ex(op2_str, 0); + } 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; } - } 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); + } + } + ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} - 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); +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; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + 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_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 { - 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); + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; } } - 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 (!(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 */ + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { - op2 = ZVAL_UNDEFINED_OP2(); + 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; } - 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; + if ((IS_TMP_VAR|IS_VAR) == 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); + } - 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); +isset_dim_obj_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(); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_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 *container, *dim, *value; + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; 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)) { + offset = _get_zval_ptr_var(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))) { + 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_ARRAY)) { - goto fetch_dim_r_array; - } else { - goto fetch_dim_r_slow; + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; } } 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); + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; } + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); } else { - zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); + 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_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } +isset_object_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); 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_DIM_IS_SPEC_TMPVAR_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 *container; + + zval *key, *subject; + HashTable *ht; + 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); + 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_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 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_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* 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 *container; - zval *offset; - void **cache_slot = NULL; + zval *expr; + zend_bool result; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = EX_VAR(opline->op2.var); + expr = _get_zval_ptr_var(opline->op1.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; +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + 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); } } - 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(); + } 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(); } - zend_wrong_property_read(offset); - ZVAL_NULL(EX_VAR(opline->result.var)); - goto fetch_obj_r_finish; - } while (0); + } 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); +} - /* 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); +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(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); + SAVE_OPLINE(); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { - Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); + 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(); + } + } - 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; - } - } - } + 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 { - 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; + 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); } } - - 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); + /* 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); + } + } } + } - 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); + if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } -fetch_obj_r_finish: + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + 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_OBJ_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_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_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_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); - } +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)); +} - /* 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_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)); +} - if (IS_CV == IS_CONST) { - name = Z_STR_P(offset); - cache_slot = CACHE_ADDR(opline->extended_value); +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)); +} - 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_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)); +} - 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); +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)); +} - if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { - Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); +/* 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; - 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; - } - } + SAVE_OPLINE(); - retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); + 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 (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); + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } - } while (0); + } -fetch_obj_is_finish: + 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(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_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_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_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); - } - } - ZEND_VM_NEXT_OPCODE(); - } + 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) { - op1_str = Z_STR_P(op1); - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - op1_str = zend_string_copy(Z_STR_P(op1)); + name = Z_STR_P(varname); } else { - 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); + name = zval_get_tmp_string(varname, &tmp_name); } - 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); + + 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); } - 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; - } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + if (!value) { + result = (opline->extended_value & ZEND_ISEMPTY); + } else { + if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); } - 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; + 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); } - 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)); + } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_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 *function_name; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; - zend_execute_data *call; - uint32_t call_info; + zval *expr; + zend_bool result; SAVE_OPLINE(); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV != IS_CONST) { - function_name = EX_VAR(opline->op2.var); - } +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; - 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(); + 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_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_CV != IS_CONST) { - - } - HANDLE_EXCEPTION(); - } - } - if (IS_CV == IS_CONST) { - function_name = EX_VAR(opline->op2.var); - } - zend_invalid_method_call(object, function_name); - + } 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(); } - } while (0); + } 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); +} - obj = Z_OBJ_P(object); - called_scope = obj->ce; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_long count; - 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; + 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); - if (IS_CV == IS_CONST) { - function_name = EX_VAR(opline->op2.var); - } + /* 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; + } + } - /* 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)); + /* 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; } - 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 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 { + count = 1; } + zend_error(E_WARNING, "%s(): Parameter must be an array or an object that implements Countable", opline->extended_value ? "sizeof" : "count"); + break; } - if (IS_CV != IS_CONST) { - - } + ZVAL_LONG(EX_VAR(opline->result.var), count); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - 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)); +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_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 */ + 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 *free_op1 = EX_VAR(opline->op1.var); - if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - zval_ptr_dtor_nogc(free_op1); + 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 { + 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; } - /* 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; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +} - call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, obj); - call->prev_execute_data = EX(call); - EX(call) = call; - +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_CASE_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - double d1, d2; + SAVE_OPLINE(); 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)); + 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)); - if (result) { - goto case_true; - } else { - goto case_false; - } - } - } - ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_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 *container; - int result; - zend_ulong hval; - zval *offset; + zval *op1, *op2; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = EX_VAR(opline->op2.var); + 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)); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; - zval *value; + 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 = 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; -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; - } + 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); } - 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 ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 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 ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { - /* avoid exception check */ + } 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); - ZEND_VM_SMART_BRANCH(result, 0); + 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 { - result = (value == NULL || !i_zend_is_true(value)); + 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); + } } - 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; + 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)); - 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_NEXT_OPCODE_CHECK_EXCEPTION(); } +} -isset_dim_obj_exit: +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_SMART_BRANCH(result, 1); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - int result; - zval *offset; + 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(); - 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); + 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); - 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 { + 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; } - } else { - result = (opline->extended_value & ZEND_ISEMPTY); - goto isset_object_finish; + 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_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; +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; - 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)); + 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) { - zend_tmp_string_release(tmp_name); - } + 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); -isset_object_finish: + 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_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)); - ZEND_VM_SMART_BRANCH(result, 1); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_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_PRE_INC_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *key, *subject; - HashTable *ht; - zend_bool result; + 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_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - subject = EX_VAR(opline->op2.var); + 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 (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; +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; } } - zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); - result = 0; - } + 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 (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } 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_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_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); - 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 { - 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); + zval *container, *dim, *value; - 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); - } + 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 { - ZVAL_COPY_VALUE(return_value, retval_ptr); + 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); } - ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -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_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *retval_ptr; + 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); - 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"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - 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; - } +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; - ZVAL_NEW_REF(EX(return_value), retval_ptr); - if (IS_TMP_VAR == IS_CONST) { - Z_TRY_ADDREF_P(retval_ptr); + 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; } } - 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); + } - retval_ptr = NULL; + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; - if (IS_TMP_VAR == IS_VAR) { - 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 { + 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; } } - 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)); + 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); - ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +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_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *retval; - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *property, *container, *result; SAVE_OPLINE(); - retval = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_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); + 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); - 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); - } + if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } - - /* 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_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value, *arg; - uint32_t arg_num = opline->op2.num; + zval *property, *container, *result; - 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); - } + 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); } - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value, *arg; - uint32_t arg_num = opline->op2.num; + zval *container; + zval *offset; + void **cache_slot = NULL; - 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)); + 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); } - 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); + + /* 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; + } } - } - ZEND_VM_NEXT_OPCODE(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *arg, *param; + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); - SAVE_OPLINE(); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } - 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); - } + 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: - 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(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 USE_OPLINE - zval *expr; - zval *result = EX_VAR(opline->result.var); - HashTable *ht; +#endif - SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + 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)); + } +} - 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); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } + 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 (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); - } - } - } + 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; } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} +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_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *array_ptr, *result; + 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); - SAVE_OPLINE(); + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; - 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_CONST == IS_CONST) { + orig_type = Z_TYPE_P(value); + } - 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; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - result = EX_VAR(opline->result.var); - ZVAL_OBJ(result, zobj); - if (IS_TMP_VAR != IS_TMP_VAR) { - GC_ADDREF(zobj); + /* 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; + } } - properties = zobj->properties; - if (properties) { - if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(properties); + } 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); } - properties = zobj->properties = zend_array_dup(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 { - properties = zobj->handlers->get_properties(zobj); } - 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); + if (!zobj->ce->__set) { - 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 (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_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); } 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)); + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + 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); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_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_TMPVAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref; + 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_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - 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); + 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; } - } else { - array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } - 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); - } - 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_TMP_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); +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 (IS_TMP_VAR == IS_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(); - } 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); + 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; } - 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); + } 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; } - 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(); - } else { - zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_VAR) { + if (!zobj->ce->__set) { - } 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 (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 { - 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_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - 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)); + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); } - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zval *ref = NULL; - int ret; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(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) { - ref = 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; } - value = Z_REFVAL_P(value); } - ret = i_zend_is_true(value); + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - 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) { + zend_tmp_string_release(tmp_name); } - if (ret) { - 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); - } - } - ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); +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(); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_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_TMPVAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - zval *ref = NULL; + zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + 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); - if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - if (IS_TMP_VAR & IS_VAR) { - ref = value; + 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; } - value = Z_REFVAL_P(value); + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } - 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); +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 (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); - } + 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_NEXT_OPCODE(); -} + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zval *result = EX_VAR(opline->result.var); + if (IS_VAR == IS_CONST) { + orig_type = Z_TYPE_P(value); + } - 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(); - } + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - 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); + /* 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; + } } } else { - ZVAL_COPY_VALUE(result, value); - } - } else { - ZVAL_COPY_VALUE(result, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { - Z_ADDREF_P(result); + 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; } } } - 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; + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } - 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)); + 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_VM_SMART_BRANCH(result, 1); -} + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - zend_bool result; + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } - 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)); +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_SMART_BRANCH(result, 1); + 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_FETCH_DIM_FUNC_ARG_SPEC_TMP_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_TMPVAR_CV_OP_DATA_CV_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_CONST == 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_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 ((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_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_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_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif +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 (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(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_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_string **rope; - zval *var; + if (UNEXPECTED(prop_info != NULL)) { + zend_uchar orig_type = IS_UNDEF; - /* 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); + if (IS_CV == 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_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 { - SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + 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; + } } - rope[opline->extended_value] = zval_get_string_func(var); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + 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; + } } } - ZEND_VM_NEXT_OPCODE(); -} -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_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } - 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); - } + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); } 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); + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { - 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(); - } + UNDEF_RESULT(); + goto exit_assign_obj; } } - for (i = 0; i <= opline->extended_value; i++) { - len += ZSTR_LEN(rope[i]); + + 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); } - 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); + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - *target = '\0'; - ZEND_VM_NEXT_OPCODE(); +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_ADD_ARRAY_ELEMENT_SPEC_TMP_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_REF_SPEC_TMPVAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; + zval *property, *container, *value_ptr; 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); - } - } - } - } + 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); - if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); - zend_string *str; - zend_ulong hval; + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); -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; - } + 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); } -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); + 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 { - 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_assign_to_property_reference(container, (IS_TMP_VAR|IS_VAR), property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -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_ptr_dtor_nogc(EX_VAR(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(); - } + 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_YIELD_SPEC_TMP_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_REF_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *property, *container, *value_ptr; 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); + 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 key */ - zval_ptr_dtor(&generator->key); + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var 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); - } - } + 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 { - 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); - + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); } } 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)); - + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr 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); - } + zend_assign_to_property_reference_var_var(container, property, value_ptr 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); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; + zend_assign_to_property_reference(container, (IS_TMP_VAR|IS_VAR), property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - /* 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)); - /* 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(); + 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|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; - HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); - zval *result; + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; - 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)); + + 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 { - result = NULL; + 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); + } } - } 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_VM_NEXT_OPCODE(); + } - 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; + 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(); + } + 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; } - } ZEND_HASH_FOREACH_END(); - } + } + 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; + } + } + 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)); - ZEND_VM_SMART_BRANCH(result, 1); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -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_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 USE_OPLINE -#endif + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; - 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)); + 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); + } + + 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"); + + 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_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(); + } + } 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 { - 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_object *orig_obj = obj; + + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); } - 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_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif + /* 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)); + } - 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)); + 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); } - 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)); } -} -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; + if (IS_CV != IS_CONST) { - /* 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); + } + + 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 { - 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); - } + /* 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 { - SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_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(); } + /* 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_ROPE_END_SPEC_TMP_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 - zend_string **rope; - zval *var, *ret; - uint32_t i; - size_t len = 0; - char *target; + zval *op1, *op2; + double d1, d2; - 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)); + 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 { - rope[opline->extended_value] = Z_STR_P(var); +case_false: + ZEND_VM_SMART_BRANCH_FALSE(); } - } else { - SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } 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; } - 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); - } - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); + } 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 (result) { + goto case_true; + } else { + goto case_false; } } } - 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(); + ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -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_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; + zval *container; + int result; + zend_ulong hval; + zval *offset; 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); + offset = EX_VAR(opline->op2.var); - } 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_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; zend_string *str; - zend_ulong hval; -add_again: +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 (IS_CV != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; + goto num_index_prop; } } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + 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: - 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)) { +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 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; + goto isset_again; } 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); + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } } - } - 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 + 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); - 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)); + 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)); } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + 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_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 { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); + 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_YIELD_SPEC_TMP_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 - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *container; + int result; + zval *offset; + 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); - - /* 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); + 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))) { + 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 { - 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); - } - - /* 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); + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; } - } 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); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); } else { - generator->send_target = NULL; + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } } - /* 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(); + 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)); - ZEND_VM_RETURN(); -} + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } -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; +isset_object_finish: - 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); } -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_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + + zval *key, *subject; + HashTable *ht; 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_not_identical_function(op1, op2); + + key = _get_zval_ptr_var(opline->op1.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_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; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + 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_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* 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) { -#if 0 USE_OPLINE -#endif + zval *retval_ptr; + zval *return_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)); + 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 { - if (IS_UNUSED == IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + 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); + } } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(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_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *retval_ptr; - 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(); - 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); + 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"); + + 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; + } + + ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } } - ZVAL_DEREF(retval_ptr); - } else if (IS_TMP_VAR == IS_CV) { - ZVAL_DEREF(retval_ptr); + break; } - if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { - ZEND_VM_NEXT_OPCODE(); - } + retval_ptr = NULL; - 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); + 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 { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + } - retval_ptr = retval_ref; + break; } } - 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(); + 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)); } - ZEND_VM_NEXT_OPCODE(); -#endif - } + + } while (0); + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -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_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; + zval *retval; - 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); - } + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - } 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); + SAVE_OPLINE(); + retval = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - 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); - } + /* 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); } } - } - - if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; - zend_string *str; - zend_ulong hval; + } 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); -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; - } + 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); } -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); + ZVAL_COPY_VALUE(&generator->retval, retval); } + } - } 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); + /* Close the generator to free up resources */ + zend_generator_close(generator, 1); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *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; } + } 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)); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + 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(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE + zval *value, *arg; + uint32_t arg_num = opline->op2.num; - 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)); + 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)); + } + 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_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(); } + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *arg, *param; 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); + 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); + } - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); + 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(); +} - /* 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; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + zval *result = EX_VAR(opline->result.var); + HashTable *ht; - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + SAVE_OPLINE(); + expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, 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_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(generator->value))) { - Z_ADDREF(generator->value); - } + 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); } - } 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; + 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 (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); } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); + } 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_MAKE_REF_EX(value_ptr, 2); + ZVAL_EMPTY_ARRAY(result); } - 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); + 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); + } } } - } - } 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 (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; } - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - -static 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)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 USE_OPLINE -#endif + zval *array_ptr, *result; - 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(); + + 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); } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } -} + Z_FE_POS_P(result) = 0; -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 + 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; - 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)); + 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); + } + 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(); + } } - 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)); + 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)); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_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 - zend_string **rope; - zval *var; + zval *array_ptr, *array_ref; - /* 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); + SAVE_OPLINE(); + + 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 { - 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); + array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + } + + 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); } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); } 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); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + array_ref = EX_VAR(opline->result.var); + ZVAL_NEW_REF(array_ref, array_ptr); + array_ptr = Z_REFVAL_P(array_ref); } - } - ZEND_VM_NEXT_OPCODE(); -} + if (IS_TMP_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); -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_TMP_VAR == IS_VAR) { - 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)); + 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 { - rope[opline->extended_value] = Z_STR_P(var); + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); } - } else { - SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + 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); } - rope[opline->extended_value] = zval_get_string_func(var); + 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(); + } 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 (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(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); } } - } - 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); + } 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_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + 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_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *ref = NULL; + int ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(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) { + ref = value; + } + 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_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); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_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); + + 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); + } + + 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); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_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)) { + 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 { + ZVAL_COPY_VALUE(result, value); + } + } else { + ZVAL_COPY_VALUE(result, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { + Z_ADDREF_P(result); + } + } + } + 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) +{ + 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); +} + +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 (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)); + } +} + +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) +{ + 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); + + 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]); @@ -19224,7 +20691,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(Z ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_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 *expr_ptr, new_expr; @@ -19264,15 +20731,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ } } - if (IS_CV != IS_UNUSED) { - zval *offset = EX_VAR(opline->op2.var); + 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_CV != IS_CONST) { + if (IS_CONST != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index; } @@ -19283,7 +20750,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_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + } 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) { @@ -19302,7 +20769,7 @@ num_index: 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) { + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { ZVAL_UNDEFINED_OP2(); str = ZSTR_EMPTY_ALLOC(); goto str_index; @@ -19320,7 +20787,7 @@ num_index: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_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; @@ -19334,14 +20801,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER 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)); + 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(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_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 @@ -19426,9 +20893,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND } /* 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) { + 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); @@ -19464,4876 +20931,2909 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_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 *closure, *var; + zval *op1; + HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + zval *result; - 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(); + 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 { - ZVAL_MAKE_REF_EX(var, 2); + result = NULL; } + } else if (Z_TYPE_P(op1) <= IS_FALSE) { + result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } 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(); + 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; } - } - ZVAL_DEREF(var); - Z_TRY_ADDREF_P(var); + } ZEND_HASH_FOREACH_END(); } - - zend_closure_bind_var_ex(closure, - (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)), var); - ZEND_VM_NEXT_OPCODE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 USE_OPLINE - zval *var_ptr; - - 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(); - } +#endif - 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; - } + 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)); } - increment_function(var_ptr); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - - 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_string **rope; + zval *var; - 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); + /* 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 { + 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(); } - - ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_string **rope; + zval *var, *ret; + uint32_t i; + size_t len = 0; + char *target; - 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); + 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); } - ZEND_VM_NEXT_OPCODE(); + } 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); + } + 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_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_NEXT_OPCODE(); } -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_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zval *expr_ptr, new_expr; 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); + 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); + } - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); - break; + } 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); + } } } - 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 ((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(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); +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; + } + } +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(); } - - ZEND_VM_TAIL_CALL(zend_pre_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_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +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 - 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(1)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + 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(); } - - ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -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_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { - ZVAL_NULL(var_ptr); - ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - 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); + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); - break; - } - } - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - increment_function(var_ptr); - } while (0); + /* 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; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); -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; + 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; - var_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_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); - 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(); - } + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - ZEND_VM_TAIL_CALL(zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); -} + /* 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)); -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 { + 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); + } - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + /* 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)); - SAVE_OPLINE(); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { - ZVAL_NULL(var_ptr); - ZVAL_UNDEFINED_OP1(); + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); } - 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 (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; + } - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); - break; - } - } - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); - decrement_function(var_ptr); - } 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(); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_RETURN(); } -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_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; + zval *op1, *op2; + zend_bool result; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + 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); +} - 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(); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; - ZEND_VM_TAIL_CALL(zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + 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); } -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_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 USE_OPLINE - zval *retval_ptr; - zval *return_value; +#endif - 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)); - } - } + 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_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); - - 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); - } + 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_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -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_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_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; - } + 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); - ZVAL_NEW_REF(EX(return_value), retval_ptr); - if (IS_VAR == IS_CONST) { - Z_TRY_ADDREF_P(retval_ptr); - } + 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); } - break; + ZVAL_DEREF(retval_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(retval_ptr); } - retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var 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) { - 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); + 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 { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); } - break; + retval_ptr = retval_ref; } } - 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(); + 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(); } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } while (0); - - ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_NEXT_OPCODE(); +#endif + } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *retval; - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *expr_ptr, new_expr; 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); - } + 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_COPY_VALUE(&generator->retval, retval); + ZVAL_MAKE_REF_EX(expr_ptr, 2); } - } - /* 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; + } 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); - 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(); + 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); + } + } + } } - 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); + if (IS_UNUSED != IS_UNUSED) { + zval *offset = NULL; + zend_string *str; + zend_ulong hval; - 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); +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; + } } +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 { - ZVAL_COPY_VALUE(arg, varptr); + zend_illegal_offset(); + zval_ptr_dtor_nogc(expr_ptr); } - } - - 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)); + } 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_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +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 - 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))) { + 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(); } - - 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_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)); - } + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - 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 (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } - 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)); - } + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - 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); + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - if (EXPECTED(Z_ISREF_P(varptr) || - ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); - } - } + /* 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; - SAVE_OPLINE(); - ZVAL_NEW_REF(arg, arg); - zend_error(E_NOTICE, "Only variables should be passed by reference"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); -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 *varptr, *arg; - uint32_t arg_num = opline->op2.num; + 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(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)); - } + /* 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); - 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); + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(Z_ISREF_P(varptr) || - QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); + /* 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 (!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)); - } + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } - 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); + /* 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 (EXPECTED(Z_ISREF_P(varptr) || - ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; } + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ SAVE_OPLINE(); - ZVAL_NEW_REF(arg, arg); - zend_error(E_NOTICE, "Only variables should be passed by reference"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + + ZEND_VM_RETURN(); } -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_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; + zval *op1; + zend_string *type; 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); + 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_MAKE_REF_EX(varptr, 2); + ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); } - ZVAL_REF(arg, Z_REF_P(varptr)); - 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_SEND_VAR_EX_SPEC_VAR_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 *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; - } - } 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); - - 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); +#endif - 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); + 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)); } - - ZEND_VM_NEXT_OPCODE(); } -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_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; + zend_string **rope; + zval *var; - if (EXPECTED(1)) { - if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_var_by_ref; + /* 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 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); - - 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 { + 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 { - ZVAL_COPY_VALUE(arg, varptr); + 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); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } - 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_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); + zend_string **rope; + zval *var, *ret; + uint32_t i; + size_t len = 0; + char *target; - 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); + 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 { - ZVAL_COPY_VALUE(arg, varptr); + 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(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_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *arg, *param; + 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); + } - 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); - } + } 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); - 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_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *expr; - zval *result = EX_VAR(opline->result.var); - HashTable *ht; - - SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - 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); - 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); + 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_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); - } - } 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_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 (IS_CV != IS_UNUSED) { + zval *offset = EX_VAR(opline->op2.var); + zend_string *str; + zend_ulong hval; + +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; } } - } +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); + } - 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_FE_RESET_R_SPEC_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 *array_ptr, *result; - - SAVE_OPLINE(); - - 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; - - 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; - - 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); - - 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); - 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(); - } + 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_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_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); } } -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_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref; - SAVE_OPLINE(); + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - 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); + 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)); } - 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); + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - 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); + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); - 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)); - } -} + /* 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; -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; + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - 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; + 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 { - 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; - } + zval *value_ptr = 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) - && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) { + /* 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 (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); - } + 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); + } - 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; + 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); } - } - 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); + } 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); } } - 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); - } + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } - 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; - array = EX_VAR(opline->op1.var); - SAVE_OPLINE(); + /* 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); - 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); - } - } - 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 ((iter = zend_iterator_unwrap(array)) == NULL) { - /* plain object */ - - 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; - } - - 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 (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(EX_VAR(opline->op1.var))].pos = pos + 1; - } 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)) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - 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))); - if (UNEXPECTED(EG(exception))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } -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; - - 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_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zval *ref = NULL; - int ret; - - SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - 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); - } - - 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); - - 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); - } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE(); -} - -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_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); - } - - 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); - - 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); - } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE(); -} - -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_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_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); - } - } else { - ZVAL_COPY_VALUE(result, value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { - Z_ADDREF_P(result); - } - } - } - 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) -{ - 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); - - if (IS_VAR == IS_CV) { - ZVAL_COPY(arg, varptr); - } else /* if (IS_VAR == IS_VAR) */ { - ZVAL_COPY_VALUE(arg, varptr); - } - - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; - - 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)); - } - - 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); - } - - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_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 = 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_VAR_CONST_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 = 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_ASSIGN_OBJ_OP_SPEC_VAR_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_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_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; - } - -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_ASSIGN_DIM_OP_SPEC_VAR_CONST_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 = 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 { - 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; - } - } - - 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 { - 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 = 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_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_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; - zval *value; - - 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_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_PRE_INC_OBJ_SPEC_VAR_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_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; - } - 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; - } - -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_POST_INC_OBJ_SPEC_VAR_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_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 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_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); - } - } else { - zend_post_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_W_SPEC_VAR_CONST_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, 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_FETCH_DIM_RW_SPEC_VAR_CONST_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, 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_FETCH_DIM_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_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)); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_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, 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_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *property, *container, *result; - - 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 & ~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_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *property, *container, *result; - - 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_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_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)) { - /* 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_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_FETCH_OBJ_UNSET_SPEC_VAR_CONST_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 = 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_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_CONST_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 = RT_CONSTANT(opline, opline->op2); - - 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_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_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_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; - } - -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); - } - 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; - } - } - } - - if (IS_CONST == IS_CV || IS_CONST == 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; - } - } - - 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: - - 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_VAR_CONST_OP_DATA_TMP_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_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); - - 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_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_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; - } - } - } - - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == 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)) { - 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); - } - -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); -} - -/* 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) -{ - USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - - 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_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); - - /* 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; - } - } - } 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; - } - } - } - - if (IS_VAR == IS_CV || IS_VAR == 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)) { - 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); - } - -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); -} - -/* 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 - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - 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); - - 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_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_CV == 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_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; - } - } - - 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; - } - } - } - - 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; - } - } - - 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: - - 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_CONST_OP_DATA_CONST_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_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 { - 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 { - 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 = RT_CONSTANT((opline+1), (opline+1)->op1); - - 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); - - } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if (IS_CONST == IS_UNUSED) { - zend_use_new_element_for_string(); - - 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); - - } - } 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); - - 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(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)); - /* 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) -{ - 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_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()); - } - 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); - - 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); - - 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)); - } + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); } - if (IS_CONST != IS_UNUSED) { + 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)); - /* assign_dim has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + + /* 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_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_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); + zval *closure, *var; - 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); - } - } + 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 { - 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()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_MAKE_REF_EX(var, 2); } } 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; + 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_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); + ZVAL_DEREF(var); + Z_TRY_ADDREF_P(var); + } - 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); + zend_closure_bind_var_ex(closure, + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)), var); + ZEND_VM_NEXT_OPCODE(); +} - 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)); +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; + + 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(); + } + + 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; } } - } - if (IS_CONST != IS_UNUSED) { + increment_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)); - /* 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_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +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 *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); + zval *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)) { + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - 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()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + 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); } - } 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; - } + 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; + + var_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(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); } - 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_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); + ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} - } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if (IS_CONST == IS_UNUSED) { - zend_use_new_element_for_string(); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; - 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); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var 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 = RT_CONSTANT(opline, opline->op2); + SAVE_OPLINE(); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_NULL(var_ptr); + ZVAL_UNDEFINED_OP1(); + } - 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: + 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(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); + break; } } - } - if (IS_CONST != IS_UNUSED) { + 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)); - /* 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_SPEC_VAR_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +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 *value; - zval *variable_ptr; + zval *var_ptr; - SAVE_OPLINE(); - value = RT_CONSTANT(opline, opline->op2); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + var_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); + 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(); } - 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(); + ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +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 *value; - zval *variable_ptr; + zval *var_ptr; - SAVE_OPLINE(); - value = RT_CONSTANT(opline, opline->op2); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + var_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); + 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(); } - 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(); + ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_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 *property, *container, *value_ptr; + zval *var_ptr; - SAVE_OPLINE(); + var_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); + SAVE_OPLINE(); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_NULL(var_ptr); + ZVAL_UNDEFINED_OP1(); + } - value_ptr = _get_zval_ptr_ptr_var((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 (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 { - 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); + 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 { - zend_assign_to_property_reference(container, IS_VAR, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); - } + 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(); +} - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; - ZEND_VM_NEXT_OPCODE_EX(1, 2); +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(); + } + + ZEND_VM_TAIL_CALL(zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -/* 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) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; + zval *var_ptr; + + 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(); + } - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = 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); - value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + 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_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +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_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); - 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 { - if (IS_CONST == IS_CONST) { - zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC 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 { - zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(return_value, retval_ptr); } } - } else { - zend_assign_to_property_reference(container, IS_VAR, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -/* 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_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 *retval_ptr; SAVE_OPLINE(); - 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)); - } + 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"); - 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"); + 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; + } - HANDLE_EXCEPTION(); - } while (0); + ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (IS_VAR == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } } + break; } - 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)); - } - - 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) { + 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; + } } - } 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 (!(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)); + if (EX(return_value)) { + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); } else { - ce = Z_CE(EX(This)); + ZVAL_MAKE_REF_EX(retval_ptr, 2); } + ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } - call_info = ZEND_CALL_NESTED_FUNCTION; - } - call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, ce); - call->prev_execute_data = EX(call); - EX(call) = call; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } while (0); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zend_class_entry *ce, *scope; - zend_class_constant *c; - zval *value, *zv; 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); - do { + /* 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 (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; + 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); - 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(); - } + 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); } - 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(); + ZVAL_COPY_VALUE(&generator->retval, retval); } - } while (0); + } - ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + /* Close the generator to free up resources */ + zend_generator_close(generator, 1); - ZEND_VM_NEXT_OPCODE(); + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; - - 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); + zval *varptr, *arg; - 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); - } - } - } + 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(); } - if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); - zend_string *str; - zend_ulong hval; + arg = ZEND_CALL_VAR(EX(call), opline->result.var); -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; - } + 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); } -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); + ZVAL_COPY_VALUE(arg, varptr); } } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + + ZEND_VM_NEXT_OPCODE(); } -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_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) { - zval *array; - uint32_t size; USE_OPLINE + zval *varptr, *arg; - 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_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZVAL_ARR(array, zend_new_array(0)); + 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_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; - zend_ulong hval; - zend_string *key; + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = RT_CONSTANT(opline, opline->op2); + 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)); + } - do { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + 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); -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 (EXPECTED(Z_ISREF_P(varptr) || + QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { - offset = ZVAL_UNDEFINED_OP2(); + } 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 (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_CONST == 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"); + + 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(); } - } while (0); + } - zval_ptr_dtor_nogc(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(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +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 *container; - zval *offset; - zend_string *name, *tmp_name; + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = RT_CONSTANT(opline, opline->op2); + 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)); + } - 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; - } + 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(); } - if (IS_CONST == IS_CONST) { - name = Z_STR_P(offset); - } else { - name = zval_try_get_tmp_string(offset, &tmp_name); - if (UNEXPECTED(!name)) { - break; - } + } 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)); } - 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); + + 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(); } - } while (0); + } - zval_ptr_dtor_nogc(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(); } -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_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *varptr, *arg; 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)); + 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)); - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); +} - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; - /* 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(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)); + } - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + 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(); + } - 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); - } - } - } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); - /* 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; - } - } - 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); + 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); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + 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 *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 { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } + ZVAL_COPY_VALUE(arg, varptr); } - } 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); + ZEND_VM_NEXT_OPCODE(); +} - 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); +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 *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 no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } 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)); } - 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; + 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(); } - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); + if (IS_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); - ZEND_VM_RETURN(); + 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_IN_ARRAY_SPEC_VAR_CONST_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 *op1; - HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); - zval *result; + zval *varptr, *arg; - 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; + 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); } - } 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; + ZVAL_COPY_VALUE(arg, varptr); + } - 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(); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *arg, *param; + + 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_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_SMART_BRANCH(result, 1); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_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 *expr; + zval *result = EX_VAR(opline->result.var); + HashTable *ht; 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 { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + expr = _get_zval_ptr_var(opline->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_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); + switch (opline->extended_value) { + case IS_LONG: + ZVAL_LONG(result, zval_get_long(expr)); 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; + 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); } - } - 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)); + /* If value is already of correct type, return it directly */ + if (Z_TYPE_P(expr) == opline->extended_value) { + ZVAL_COPY_VALUE(result, expr); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); } - } 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; + 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); } + } else { + ZVAL_EMPTY_ARRAY(result); } - - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + } 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 { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr); + ZVAL_EMPTY_ARRAY(result); } - 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_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 { - zend_binary_op(zptr, zptr, value OPLINE_CC); + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } - } 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); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - zval *value, *container, *dim; + zval *array_ptr, *result; 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 = _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; + 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; + + 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; + + 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); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } 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); + 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 { - 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; + 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; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); +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; - 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; - } - } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); + SAVE_OPLINE(); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + 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); } - 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; + 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); - 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++; + 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); } - 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(); + 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); } - ZVAL_ARR(container, zend_new_array(8)); - goto assign_dim_op_new_array; + 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_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)); + 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)); } - - 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; + zval *array; 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); - - 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 (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++; } - 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(); -} + 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; -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; + ZEND_ASSERT(Z_TYPE_P(array) == IS_OBJECT); + if ((iter = zend_iterator_unwrap(array)) == NULL) { + /* plain object */ - 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); + 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; + } - 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; + 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 (IS_VAR == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + 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_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); + EG(ht_iterators)[Z_FE_ITER_P(array)].pos = pos + 1; } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { + 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(); - break; + 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); + 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 { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); + ZVAL_LONG(EX_VAR(opline->result.var), iter->index); } - 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); + value_type = Z_TYPE_INFO_P(value); } - } while (0); + } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + 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_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_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 *array; + zval *value; + uint32_t value_type; + HashTable *fe_ht; + HashPosition pos; + Bucket *p; + array = EX_VAR(opline->op1.var); 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 post_incdec_object; + 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; } - if (IS_VAR == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + 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; + } } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; + pos++; + p++; } - -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; + 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); } } - 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); + 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 ((iter = zend_iterator_unwrap(array)) == NULL) { + /* plain object */ + + 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; } - zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC 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)) { + 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 (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(EX_VAR(opline->op1.var))].pos = pos + 1; } else { - zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + 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)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + 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); } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); + } 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(); } - } 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_W_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_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); +fe_fetch_w_exit: + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); } - 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) -{ - 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)); - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + 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); } - 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) -{ -#if 0 - USE_OPLINE -#endif + if (EXPECTED(opline->op2_type == IS_CV)) { + zval *variable_ptr = EX_VAR(opline->op2.var); + if (EXPECTED(variable_ptr != value)) { + zend_reference *ref; - 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 { - 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)); + ref = Z_REF_P(value); + GC_ADDREF(ref); + i_zval_ptr_dtor(variable_ptr); + ZVAL_REF(variable_ptr, ref); } - 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); + } else { + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->op2.var), Z_REF_P(value)); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_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 *property, *container, *result; + zval *value; + zval *ref = NULL; + int ret; SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - 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); + 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); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -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; + ret = i_zend_is_true(value); - 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); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -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 (ret) { + zval *result = EX_VAR(opline->result.var); - 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)); + 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); + + 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_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)); + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *property, *result; + zval *value; + zval *ref = NULL; 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(); -} + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *dim; + if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (IS_VAR & IS_VAR) { + ref = value; + } + value = Z_REFVAL_P(value); + } - 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 (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); - 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); + 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); } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_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 *object, *property, *value, tmp; - 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); - value = RT_CONSTANT((opline+1), (opline+1)->op1); + zval *value; + zval *result = EX_VAR(opline->result.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; + 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(); } -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; - } + 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 { - 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; + ZVAL_COPY_VALUE(result, value); + } + } else { + ZVAL_COPY_VALUE(result, value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { + Z_ADDREF_P(result); } } } + ZEND_VM_NEXT_OPCODE(); +} - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - ZVAL_DEREF(value); - } +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; - 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)) { + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); - UNDEF_RESULT(); - goto exit_assign_obj; - } + if (IS_VAR == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); } - value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + ZEND_VM_NEXT_OPCODE(); +} - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; + + 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)); } -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + 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); } -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_VAR_TMPVAR_OP_DATA_TMP_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 *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *op1, *op2; + zend_bool result; 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); - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + 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)); - 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_SMART_BRANCH(result, 1); +} -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; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; - 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); + 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)); - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; + ZEND_VM_SMART_BRANCH(result, 1); +} - if (IS_TMP_VAR == IS_CONST) { - orig_type = Z_TYPE_P(value); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var 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 (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 (!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 (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 (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(value); - } + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(property); + 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 { - 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 (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; + } } - } - value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + dim = RT_CONSTANT(opline, opline->op2); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); + 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)); + } + } } -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)); - /* 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_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *var_ptr; + zval *value; 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); - value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + value = RT_CONSTANT(opline, opline->op2); + var_ptr = _get_zval_ptr_ptr_var(opline->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; + 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_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; + 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); + } - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - if (IS_VAR == IS_CONST) { - orig_type = Z_TYPE_P(value); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_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; - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = 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; - } + 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(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_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 (!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; +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; } } - } - - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(value); - } + 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); + } - 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; + 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); } - } - - 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); - } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); -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)); - /* 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_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *container; 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); - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + 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_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_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} -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; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; - 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); + 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 (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - if (IS_CV == IS_CONST) { - orig_type = Z_TYPE_P(value); - } +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 - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + 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)); + } +} - /* 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; - } - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; - if (!zobj->ce->__set) { + 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 (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; - } - } + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(value); - } +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_VAR) == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { + 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); - UNDEF_RESULT(); - goto exit_assign_obj; - } + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim; - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = RT_CONSTANT(opline, opline->op2); -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + 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); } -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_CHECK_EXCEPTION(); } -/* 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -24347,7 +23847,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_CONST == IS_UNUSED) { value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); @@ -24375,8 +23875,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 = 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); @@ -24398,21 +23898,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 = RT_CONSTANT(opline, opline->op2); 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_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); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + 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); @@ -24421,7 +23921,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 = RT_CONSTANT(opline, opline->op2); UNDEF_RESULT(); } else { @@ -24430,7 +23930,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -24438,15 +23938,15 @@ assign_dim_error: } } } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CONST != 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_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -24460,7 +23960,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_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); @@ -24488,8 +23988,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 = 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); @@ -24511,22 +24011,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 = RT_CONSTANT(opline, opline->op2); 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_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); 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_CONST == 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 = 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)); @@ -24535,7 +24035,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 = RT_CONSTANT(opline, opline->op2); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -24544,7 +24044,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + 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))) { @@ -24552,15 +24052,15 @@ assign_dim_error: } } } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CONST != 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_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -24574,7 +24074,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_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); @@ -24602,8 +24102,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 = 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); @@ -24625,22 +24125,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 = RT_CONSTANT(opline, opline->op2); 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_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); 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_CONST == 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 = 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)); @@ -24649,7 +24149,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 = RT_CONSTANT(opline, opline->op2); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -24658,7 +24158,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + 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))) { @@ -24666,15 +24166,15 @@ assign_dim_error: } } } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CONST != 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_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -24688,7 +24188,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_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); @@ -24716,8 +24216,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 = 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); @@ -24739,21 +24239,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 = RT_CONSTANT(opline, opline->op2); 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_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); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + 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); @@ -24762,7 +24262,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 = RT_CONSTANT(opline, opline->op2); UNDEF_RESULT(); } else { @@ -24771,7 +24271,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -24779,89 +24279,55 @@ assign_dim_error: } } } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CONST != 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_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_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 *property, *container, *value_ptr; + zval *value; + zval *variable_ptr; SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + variable_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 = _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); + 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)); - 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_assign_to_variable() always takes care of op2, never free it! */ + + 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_VAR_TMPVAR_OP_DATA_CV_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 *property, *container, *value_ptr; + zval *value; + zval *variable_ptr; SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + variable_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 = _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); + 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); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ - 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_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_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -24879,10 +24345,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_CONST != IS_CONST) { CACHE_PTR(opline->result.num, ce); } } @@ -24890,7 +24356,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 { @@ -24898,31 +24364,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_CONST == 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_CONST == 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_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_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + 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_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + } 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"); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } while (0); } @@ -24931,24 +24397,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_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)); } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + 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_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CONST != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -24995,7 +24461,79 @@ 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_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) { USE_OPLINE zval *expr_ptr, new_expr; @@ -25035,15 +24573,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_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_TMP_VAR|IS_VAR) != IS_CONST) { + if (IS_CONST != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index; } @@ -25054,7 +24592,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_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + } 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) { @@ -25073,7 +24611,7 @@ num_index: 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) { + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { ZVAL_UNDEFINED_OP2(); str = ZSTR_EMPTY_ALLOC(); goto str_index; @@ -25081,7 +24619,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(); @@ -25091,7 +24629,7 @@ num_index: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_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; @@ -25105,14 +24643,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HAN 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)); + 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(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -25122,7 +24660,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HAND 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); + offset = RT_CONSTANT(opline, opline->op2); do { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -25134,7 +24672,7 @@ unset_dim_array: offset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { key = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (IS_CONST != IS_CONST) { if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } @@ -25149,7 +24687,7 @@ str_index_dim: 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)) { + } 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) { @@ -25167,7 +24705,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_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { ZVAL_UNDEFINED_OP2(); key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; @@ -25184,11 +24722,11 @@ num_index_dim: 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)) { + 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_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); @@ -25197,12 +24735,11 @@ 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_TMPVAR_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 *container; @@ -25211,7 +24748,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND 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); + offset = RT_CONSTANT(opline, opline->op2); do { if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { @@ -25228,7 +24765,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND break; } } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (IS_CONST == IS_CONST) { name = Z_STR_P(offset); } else { name = zval_try_get_tmp_string(offset, &tmp_name); @@ -25236,18 +24773,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND break; } } - 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) { + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { zend_tmp_string_release(tmp_name); } } while (0); - 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_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -25333,13 +24869,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_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); - 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 @@ -25365,189 +24900,50 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER( * 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_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! */ + /* 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_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *variable_ptr; - zval *value_ptr; + zval *op1; + HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + zval *result; 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); + 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_assign_to_variable_reference(variable_ptr, value_ptr); - } + zend_string *key; + zval key_tmp, *val; - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_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(); } - - 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_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -25560,15 +24956,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_ assign_dim_op_array: SEPARATE_ARRAY(container); assign_dim_op_new_array: - dim = NULL; - if (IS_UNUSED == IS_UNUSED) { + 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; } } else { - if (IS_UNUSED == IS_CONST) { + 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); @@ -25581,7 +24977,7 @@ assign_dim_op_new_array: 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))) { + 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))) { @@ -25604,10 +25000,10 @@ assign_dim_op_new_array: } } - dim = NULL; + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_UNUSED == 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_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); @@ -25626,41 +25022,140 @@ assign_dim_op_ret_null: } } + 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_FETCH_DIM_W_SPEC_VAR_UNUSED_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 *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); + } + } 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); + } + } 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_W_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_W(container, NULL, IS_UNUSED OPLINE_CC 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(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_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_RW(container, NULL, IS_UNUSED OPLINE_CC 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); } 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -25670,16 +25165,71 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UN 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)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - if (IS_UNUSED == IS_UNUSED) { + 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_NULL_HANDLER(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_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_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 *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); + } + + 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) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -25693,7 +25243,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if (IS_UNUSED == 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); @@ -25721,8 +25271,8 @@ try_assign_dim_array: } } } else { - dim = NULL; - if (IS_UNUSED == 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); @@ -25744,21 +25294,21 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (IS_UNUSED == 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_UNUSED == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); UNDEF_RESULT(); } else { - dim = NULL; + 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); @@ -25767,7 +25317,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 = NULL; + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -25776,7 +25326,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = NULL; + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25784,15 +25334,15 @@ assign_dim_error: } } } - if (IS_UNUSED != 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_UNUSED_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; @@ -25806,7 +25356,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if (IS_UNUSED == 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); @@ -25834,8 +25384,8 @@ try_assign_dim_array: } } } else { - dim = NULL; - if (IS_UNUSED == 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); @@ -25857,22 +25407,22 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; + 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_UNUSED == 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_UNUSED == 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 = NULL; + 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)); @@ -25881,7 +25431,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 = NULL; + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -25890,7 +25440,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = NULL; + 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))) { @@ -25898,15 +25448,15 @@ assign_dim_error: } } } - if (IS_UNUSED != 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_UNUSED_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; @@ -25920,7 +25470,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if (IS_UNUSED == 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); @@ -25948,8 +25498,8 @@ try_assign_dim_array: } } } else { - dim = NULL; - if (IS_UNUSED == 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); @@ -25971,22 +25521,22 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; + 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_UNUSED == 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_UNUSED == 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 = NULL; + 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)); @@ -25995,7 +25545,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 = NULL; + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -26004,7 +25554,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = NULL; + 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))) { @@ -26012,15 +25562,15 @@ assign_dim_error: } } } - if (IS_UNUSED != 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_UNUSED_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; @@ -26034,7 +25584,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); - if (IS_UNUSED == 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); @@ -26062,8 +25612,8 @@ try_assign_dim_array: } } } else { - dim = NULL; - if (IS_UNUSED == 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); @@ -26085,21 +25635,21 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; + 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_UNUSED == 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_UNUSED == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); UNDEF_RESULT(); } else { - dim = NULL; + 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); @@ -26108,7 +25658,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 = NULL; + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -26117,7 +25667,7 @@ try_assign_dim_array: } } else { zend_use_scalar_as_array(); - dim = NULL; + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -26125,15 +25675,15 @@ assign_dim_error: } } } - if (IS_UNUSED != 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_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +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; @@ -26151,10 +25701,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_UNUSED != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { CACHE_PTR(opline->result.num, ce); } } @@ -26162,7 +25712,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 { @@ -26170,233 +25720,104 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } if (IS_VAR == IS_CONST && - IS_UNUSED == 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_UNUSED == 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_UNUSED != IS_UNUSED) { - function_name = NULL; - if (IS_UNUSED != 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_UNUSED & (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_UNUSED == 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); } } - 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)); - } - - 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) { - - } - } 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 (!(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; - } - - 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_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); + 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)); } - } 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)); + 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 && + 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)); + } } 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))) { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); 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); + 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); } + } - /* 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 (!(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 { - if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { - init_func_run_time_cache(&constructor->op_array); + /* 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)); + } } - /* 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_info = ZEND_CALL_NESTED_FUNCTION; } + 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_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_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -26436,15 +25857,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU } } - if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; + 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_UNUSED != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index; } @@ -26455,7 +25876,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_UNUSED & (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) { @@ -26474,7 +25895,7 @@ num_index: 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) { + } 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; @@ -26482,7 +25903,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(); @@ -26492,7 +25913,7 @@ num_index: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_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; @@ -26506,29 +25927,149 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HAN 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_UNUSED_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_SEPARATE_SPEC_VAR_UNUSED_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 *var_ptr; + zval *container; + zval *offset; + zend_ulong hval; + zend_string *key; - 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); + 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"); + } + } while (0); - ZEND_VM_NEXT_OPCODE(); + 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_UNUSED_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; + 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; + } + } + 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_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -26614,12 +26155,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( } /* 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) { + 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 @@ -26652,155 +26194,182 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_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 = EX_VAR(opline->op1.var); + zval *op1, *op2; + zend_bool result; - 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); + 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); } - ZEND_VM_NEXT_OPCODE(); + 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_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; - zend_string *type; + 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); - 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"); + 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_OBJ_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_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 *variable_ptr; 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); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + 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! */ - 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; - } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} -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; +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; - 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; - } - } + 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_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 (IS_VAR == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { - 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_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); + 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); } - } while (0); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr); + } - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + 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)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -26813,15 +26382,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND assign_dim_op_array: SEPARATE_ARRAY(container); assign_dim_op_new_array: - dim = EX_VAR(opline->op2.var); - if (IS_CV == 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_CV == 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); @@ -26834,7 +26403,7 @@ assign_dim_op_new_array: 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))) { + 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))) { @@ -26857,10 +26426,10 @@ assign_dim_op_new_array: } } - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + dim = NULL; if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + 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); @@ -26883,907 +26452,1361 @@ assign_dim_op_ret_null: ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CV_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 *var_ptr; + 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) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; zval *value; + zval *variable_ptr; + zval *dim; 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); + 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 (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value 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_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)) { + + 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 { + 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()); } - 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); + } + } 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 (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + 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(); + } else { + ZVAL_ARR(object_ptr, zend_new_array(8)); + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = NULL; +assign_dim_error: + + 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)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CV_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; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; 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); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->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 pre_incdec_object; + 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); } - if (IS_VAR == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + 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; + } + 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; } - 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); -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)) { + 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)); UNDEF_RESULT(); - break; + } 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)); + } + } 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; + } + } 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)); } } - 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)); + } + 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_VAR_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 = _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_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); + } 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); } - 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); + 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 = _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()); } - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } - } while (0); + } 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 = _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); + + 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)); + } + } 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; + } + } 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)); + } + } + } + if (IS_UNUSED != 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_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_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; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; 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); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->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(); + 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); } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; - } + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(variable_ptr == NULL)) { -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); + 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 { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - break; + 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 = _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()); } - 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)); + 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 = _get_zval_ptr_cv_deref_BP_VAR_R((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); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_UNUSED == IS_UNUSED) { + zend_use_new_element_for_string(); + + UNDEF_RESULT(); } 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); - } + 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); - zend_post_incdec_property_zval(zptr, prop_info 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(); + } else { + ZVAL_ARR(object_ptr, zend_new_array(8)); + goto try_assign_dim_array; } } 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); + zend_use_scalar_as_array(); + dim = NULL; +assign_dim_error: + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } } - } while (0); + } + if (IS_UNUSED != 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_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_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 *container; + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; 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_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + 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)); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; + 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"); - 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); + HANDLE_EXCEPTION(); + } while (0); + } + } - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + 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)); + } -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 + 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) { - 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 (IS_CV == IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(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); } - 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; + 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(); - 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); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; - 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_W_SPEC_VAR_CV_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 - zval *property, *container, *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 & ~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_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_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + 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); + } -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; + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } - 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); + 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; + } + } - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + 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 } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 USE_OPLINE -#endif + zval *result; + zend_function *constructor; + zend_class_entry *ce; + zend_execute_data *call; - 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)); + 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(); } - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_VAR_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)); + ce = Z_CE_P(EX_VAR(opline->op1.var)); } -} - -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); + if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) { + ZVAL_UNDEF(result); + HANDLE_EXCEPTION(); } - 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; + constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); + if (constructor == NULL) { + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - dim = EX_VAR(opline->op2.var); + /* 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); + } - 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); + /* 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 { - zend_fetch_dimension_address_W(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); + 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_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + call->prev_execute_data = EX(call); + EX(call) = call; + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *expr_ptr, new_expr; 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); - 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; + 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); } - 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_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); - - 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); + 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); - /* 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; + 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_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); +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_CONST == IS_CV || IS_CONST == 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); } } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); +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) { - zend_tmp_string_release(tmp_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)); + } + 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(); } +} -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; -exit_assign_obj: + 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); + } + } - 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_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_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_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); + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - 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; + 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_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 (IS_TMP_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_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); + } + } + } else { + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var 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 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; + } } - 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); + 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); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.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); - } - 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_var(opline->op1.var EXECUTE_DATA_CC); - 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); - } + /* 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); } - 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_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); } - goto exit_assign_obj; } } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } - if (IS_TMP_VAR == IS_CV || IS_TMP_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 (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 (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); } - 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); + 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; } -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: + /* 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)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + /* 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(); } -/* 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_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_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); + zval *op1 = EX_VAR(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; + 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)); } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + } 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); } + ZEND_VM_NEXT_OPCODE(); +} -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_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_string *type; - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; + 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)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - if (IS_VAR == IS_CONST) { - orig_type = Z_TYPE_P(value); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.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 (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 (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_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 (!zobj->ce->__set) { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - 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); + 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; } - 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); + } 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 (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(value); + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + 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(); + } + 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_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; + 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_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value; + + 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); + + 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; + } } - } - - 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); - } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); -free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - 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); + 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_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + 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); + 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 (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; + 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; } - 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_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); - - if (UNEXPECTED(prop_info != NULL)) { - zend_uchar orig_type = IS_UNDEF; - - if (IS_CV == 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_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; - } - } +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 { - 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; - } + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; } - - if (!zobj->ce->__set) { - - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } + } + 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) { - 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); + 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); } - 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 (IS_CV != 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_W_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_W(container, EX_VAR(opline->op2.var), IS_CV 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(); +} - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(value); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_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_RW(container, EX_VAR(opline->op2.var), IS_CV 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(); +} - if (IS_CV == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { +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 - UNDEF_RESULT(); - goto exit_assign_obj; + 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 (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)); } +} - value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); + 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); + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(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); +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); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} -exit_assign_obj: +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - 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); + + 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); + } + + 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_DIM_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -28312,80 +28335,6 @@ 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 @@ -29533,7 +29482,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) { + if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -29550,7 +29499,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) { + if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -29675,7 +29624,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|IS_TMP_VAR))) { + if (IS_UNUSED == 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_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -31400,7 +31349,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) { + if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -31417,7 +31366,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) { + if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -31542,7 +31491,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|IS_TMP_VAR))) { + if (IS_UNUSED == 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_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -33795,7 +33744,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) { + if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -33812,7 +33761,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) { + if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -33937,7 +33886,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|IS_TMP_VAR))) { + if (IS_UNUSED == 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_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -38107,7 +38056,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) { + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -38124,7 +38073,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) { + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -38249,7 +38198,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|IS_TMP_VAR))) { + if (IS_CV == 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_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -41585,7 +41534,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) { + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -41602,7 +41551,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) { + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -41727,7 +41676,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|IS_TMP_VAR))) { + if (IS_CV == 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_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -46393,7 +46342,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) { + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -46410,7 +46359,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) { + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -46535,7 +46484,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|IS_TMP_VAR))) { + if (IS_CV == 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_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -49495,56 +49444,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_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_TMPVAR_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, @@ -49655,16 +49604,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_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_TMPVAR_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, @@ -49733,13 +49682,19 @@ 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, @@ -49747,40 +49702,34 @@ 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_VAR_TMPVAR_OP_DATA_CV_LABEL, + (void*)&&ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR_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_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_ASSIGN_OBJ_REF_SPEC_TMPVAR_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, @@ -50195,16 +50144,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_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_TMPVAR_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, @@ -50250,16 +50199,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_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_TMPVAR_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, @@ -50360,16 +50309,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_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_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_NULL_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_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_NULL_LABEL, - (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_LABEL, + (void*)&&ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_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, @@ -50635,16 +50584,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_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_TMPVAR_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, @@ -53472,6 +53421,14 @@ 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); @@ -53484,10 +53441,46 @@ 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); @@ -53568,6 +53561,14 @@ 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); @@ -53580,10 +53581,46 @@ 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); @@ -53676,6 +53713,14 @@ 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); @@ -53688,10 +53733,46 @@ 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); @@ -53849,10 +53930,6 @@ 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); @@ -53881,10 +53958,6 @@ 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); @@ -53941,10 +54014,6 @@ 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); @@ -54158,10 +54227,6 @@ 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); @@ -54170,10 +54235,6 @@ 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); @@ -54194,18 +54255,6 @@ 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); @@ -54214,22 +54263,6 @@ 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); @@ -54254,14 +54287,6 @@ 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); @@ -54294,10 +54319,6 @@ 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); @@ -54306,10 +54327,6 @@ 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); @@ -54330,18 +54347,6 @@ 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); @@ -54350,22 +54355,6 @@ 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); @@ -54382,14 +54371,6 @@ 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); @@ -54518,10 +54499,6 @@ 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); @@ -54530,10 +54507,6 @@ 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); @@ -54554,18 +54527,6 @@ 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); @@ -54574,22 +54535,6 @@ 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); @@ -54618,14 +54563,6 @@ 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); @@ -57039,56 +56976,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_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_TMPVAR_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, @@ -57199,16 +57136,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_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_TMPVAR_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, @@ -57277,13 +57214,19 @@ 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, @@ -57291,40 +57234,34 @@ 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_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_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER, @@ -57739,16 +57676,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_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_TMPVAR_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, @@ -57794,16 +57731,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_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_TMPVAR_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, @@ -57904,16 +57841,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_TMP_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_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_NULL_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_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_NULL_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_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, @@ -58179,16 +58116,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_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_TMPVAR_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 e5d50a4083..870506e8e2 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -436,22 +436,38 @@ _(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) \ - _(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) \ + _(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) \ _(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) \ @@ -506,10 +522,14 @@ _(1038, ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR) \ _(1039, ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED) \ _(1040, ZEND_ASSIGN_DIM_OP_SPEC_CV_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) \ + _(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) \ _(1056, ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONST) \ _(1057, ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR) \ _(1058, ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR) \ @@ -527,14 +547,22 @@ _(1093, ZEND_QM_ASSIGN_SPEC_TMP) \ _(1094, ZEND_QM_ASSIGN_SPEC_VAR) \ _(1096, ZEND_QM_ASSIGN_SPEC_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) \ + _(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) \ _(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) \ @@ -789,10 +817,14 @@ _(1578, ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR) \ _(1579, ZEND_FETCH_DIM_W_SPEC_CV_UNUSED) \ _(1580, ZEND_FETCH_DIM_W_SPEC_CV_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) \ + _(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) \ _(1596, ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST) \ _(1597, ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR) \ _(1598, ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR) \ @@ -815,10 +847,14 @@ _(1633, ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR) \ _(1634, ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED) \ _(1635, ZEND_FETCH_DIM_RW_SPEC_CV_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) \ + _(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) \ _(1651, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST) \ _(1652, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR) \ _(1653, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR) \ @@ -895,14 +931,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_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) \ + _(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) \ _(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) \ @@ -1079,10 +1115,14 @@ _(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) \ - _(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) \ + _(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) \ _(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 65733779e4..143bac1960 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, - 0x00040751, + 0x00040755, 0x00040000, 0x04000701, 0x04006701, - 0x04000751, + 0x04000755, 0x04000000, 0x0b000101, 0x00000003, - 0x0b040751, + 0x0b040755, 0x0b040000, 0x00000001, 0x00000001, @@ -306,16 +306,16 @@ static uint32_t zend_vm_opcodes_flags[195] = { 0x00040757, 0x00010107, 0x00006701, - 0x00640751, + 0x00640755, 0x00010107, 0x00006701, - 0x00040751, + 0x00040755, 0x00010107, 0x00000707, 0x00040757, 0x00010107, 0x00006703, - 0x00240753, + 0x00240757, 0x00010107, 0x00000701, 0x00040751, @@ -353,7 +353,7 @@ static uint32_t zend_vm_opcodes_flags[195] = { 0x00000000, 0x00000000, 0x00000000, - 0x00040751, + 0x00040755, 0x00040751, 0x00040751, 0x00040751, diff --git a/ext/simplexml/tests/bug35785.phpt b/ext/simplexml/tests/bug35785.phpt index 420515bb03..9ffea71e30 100644 --- a/ext/simplexml/tests/bug35785.phpt +++ b/ext/simplexml/tests/bug35785.phpt @@ -12,15 +12,9 @@ $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(); ?> ---EXPECT-- - -FooBar -bool(false) - -FooBar - -FooBar +--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 diff --git a/ext/simplexml/tests/bug41582.phpt b/ext/simplexml/tests/bug41582.phpt index b270f3b639..a896530dc3 100644 --- a/ext/simplexml/tests/bug41582.phpt +++ b/ext/simplexml/tests/bug41582.phpt @@ -13,6 +13,5 @@ $xml->movie[]->characters->character[0]->name = 'Miss Coder'; echo($xml->asXml()); ?> ---EXPECT-- - -Miss Coder +--EXPECTF-- +Fatal error: Cannot use [] for reading in %s on line %d