diff --git a/Zend/Optimizer/zend_dump.c b/Zend/Optimizer/zend_dump.c index 1de9519469538..dc61196462d31 100644 --- a/Zend/Optimizer/zend_dump.c +++ b/Zend/Optimizer/zend_dump.c @@ -609,12 +609,14 @@ ZEND_API void zend_dump_op(const zend_op_array *op_array, const zend_basic_block fprintf(stderr, " (ref)"); } } - if ((ZEND_VM_EXT_DIM_WRITE|ZEND_VM_EXT_FETCH_REF) & flags) { + if ((ZEND_VM_EXT_DIM_WRITE|ZEND_VM_EXT_OBJ_W_CONTAINER|ZEND_VM_EXT_FETCH_REF) & flags) { uint32_t obj_flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS; if (obj_flags == ZEND_FETCH_REF) { fprintf(stderr, " (ref)"); } else if (obj_flags == ZEND_FETCH_DIM_WRITE) { fprintf(stderr, " (dim write)"); + } else if (obj_flags == ZEND_FETCH_OBJ_W_CONTAINER) { + fprintf(stderr, " (obj container)"); } } } diff --git a/Zend/tests/031.phpt b/Zend/tests/031.phpt index 116a0e8f2c5d4..7701d2f851bb7 100644 --- a/Zend/tests/031.phpt +++ b/Zend/tests/031.phpt @@ -8,4 +8,7 @@ test($arr[]); ?> --EXPECTF-- -Fatal error: Cannot use [] for reading in %s on line %d +Fatal error: Uncaught Error: Cannot use [] for reading in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/033.phpt b/Zend/tests/033.phpt index 6593d6ba4ad44..9b463e0333dcc 100644 --- a/Zend/tests/033.phpt +++ b/Zend/tests/033.phpt @@ -62,5 +62,17 @@ Warning: Trying to access array offset on null in %s on line %d Warning: Trying to access array offset on null in %s on line %d Warning: Attempt to read property "foo" on null in %s on line %d + +Warning: Undefined variable $arr in %s on line %d + +Warning: Trying to access array offset on null in %s on line %d + +Warning: Trying to access array offset on null in %s on line %d + +Warning: Trying to access array offset on null in %s on line %d + +Warning: Trying to access array offset on null in %s on line %d + +Warning: Trying to access array offset on null in %s on line %d Attempt to assign property "foo" on null -Attempt to assign property "bar" on null +Cannot use [] for reading diff --git a/Zend/tests/bug41351.phpt b/Zend/tests/bug41351.phpt index 6e40669341d8c..d7f030c96f441 100644 --- a/Zend/tests/bug41351.phpt +++ b/Zend/tests/bug41351.phpt @@ -11,4 +11,7 @@ foreach($a[] as $b) { echo "Done\n"; ?> --EXPECTF-- -Fatal error: Cannot use [] for reading in %s on line %d +Fatal error: Uncaught Error: Cannot use [] for reading in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug41351_2.phpt b/Zend/tests/bug41351_2.phpt index 0a36189d747ee..20bba771df540 100644 --- a/Zend/tests/bug41351_2.phpt +++ b/Zend/tests/bug41351_2.phpt @@ -11,4 +11,7 @@ foreach($a[]['test'] as $b) { echo "Done\n"; ?> --EXPECTF-- -Fatal error: Cannot use [] for reading in %s on line %d +Fatal error: Uncaught Error: Cannot use [] for reading in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug41351_3.phpt b/Zend/tests/bug41351_3.phpt index 0137ff7920d9c..e7d0b389413ea 100644 --- a/Zend/tests/bug41351_3.phpt +++ b/Zend/tests/bug41351_3.phpt @@ -11,4 +11,9 @@ foreach($a['test'][] as $b) { echo "Done\n"; ?> --EXPECTF-- -Fatal error: Cannot use [] for reading in %s on line %d +Warning: Undefined array key "test" in %s on line %d + +Fatal error: Uncaught Error: Cannot use [] for reading in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug41813.phpt b/Zend/tests/bug41813.phpt new file mode 100644 index 0000000000000..1fd9518cf90a0 --- /dev/null +++ b/Zend/tests/bug41813.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #41813 (segmentation fault when using string offset as an object) +--FILE-- +bar = "xyz"; + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Uncaught Error: Attempt to assign property "bar" on string 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 new file mode 100644 index 0000000000000..a70de3902551d --- /dev/null +++ b/Zend/tests/bug41919.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #41919 (crash in string to array conversion) +--FILE-- +bar[1] = "bang"; + +echo "ok\n"; +?> +--EXPECTF-- +Warning: Uninitialized string offset 3 in %s on line %d + +Fatal error: Uncaught Error: Attempt to modify property "bar" on string 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 new file mode 100644 index 0000000000000..d199d195375d3 --- /dev/null +++ b/Zend/tests/bug47704.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #47704 (crashes on some "bad" operations with string offsets) +--FILE-- +a += 1; +?> +--EXPECTF-- +Fatal error: Uncaught Error: Attempt to assign property "a" on string 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 7debab3f8bebb..238323c9de563 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" on null Warning: Undefined variable $x in %s on line %d -Attempt to modify property "a" on null + +Warning: Attempt to read property "a" on null in %s on line %d +Attempt to assign property "b" on null Warning: Undefined variable $x in %s on line %d Attempt to increment/decrement property "a" on null Warning: Undefined variable $x in %s on line %d -Attempt to modify property "a" on null + +Warning: Attempt to read property "a" on null in %s on line %d +Attempt to increment/decrement property "b" on null Warning: Undefined variable $x in %s on line %d Attempt to assign property "a" on null Warning: Undefined variable $x in %s on line %d -Attempt to modify property "a" on null + +Warning: Attempt to read property "a" on null in %s on line %d +Attempt to assign property "b" on null Warning: Undefined variable $x in %s on line %d diff --git a/Zend/tests/bug55007.phpt b/Zend/tests/bug55007.phpt index fe8dfb3dcbcbd..e75d233702169 100644 --- a/Zend/tests/bug55007.phpt +++ b/Zend/tests/bug55007.phpt @@ -4,7 +4,7 @@ Bug #55007 (compiler fail after previous fail) --EXPECTF-- -Fatal error: Cannot use [] for reading in %s(%d) : eval()'d code on line %d +Fatal error: Cannot use 'int' as class name as it is reserved in %s on line %d My error handler runs. diff --git a/Zend/tests/bug75921.phpt b/Zend/tests/bug75921.phpt index ab82c85840c43..f75a9881e99b9 100644 --- a/Zend/tests/bug75921.phpt +++ b/Zend/tests/bug75921.phpt @@ -53,15 +53,29 @@ Attempt to modify property "a" on null Warning: Undefined variable $null in %s on line %d NULL -Attempt to modify property "a" on null + +Warning: Undefined variable $null in %s on line %d + +Warning: Attempt to read property "a" on null in %s on line %d +Attempt to assign property "b" on null Warning: Undefined variable $null in %s on line %d NULL -Attempt to modify property "a" on null + +Warning: Undefined variable $null in %s on line %d + +Warning: Attempt to read property "a" on null in %s on line %d + +Warning: Trying to access array offset on null in %s on line %d +Attempt to assign property "b" on null Warning: Undefined variable $null in %s on line %d NULL -Attempt to modify property "a" on null + +Warning: Undefined variable $null in %s on line %d + +Warning: Attempt to read property "a" on null in %s on line %d +Attempt to modify property "b" on null Warning: Undefined variable $null in %s on line %d NULL diff --git a/Zend/tests/bug78531.phpt b/Zend/tests/bug78531.phpt index b818afb79a863..f16052d3357eb 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" on null Warning: Undefined variable $u4 in %s on line %d -Attempt to modify property "a" on null + +Warning: Attempt to read property "a" on null in %s on line %d +Attempt to assign property "a" on null diff --git a/Zend/tests/errmsg_006.phpt b/Zend/tests/errmsg_006.phpt index 1165770d4b066..797b87c4d9459 100644 --- a/Zend/tests/errmsg_006.phpt +++ b/Zend/tests/errmsg_006.phpt @@ -9,4 +9,7 @@ $b = $a[]; echo "Done\n"; ?> --EXPECTF-- -Fatal error: Cannot use [] for reading in %s on line %d +Fatal error: Uncaught Error: Cannot use [] for reading in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/new_offset_assign_obj.phpt b/Zend/tests/new_offset_assign_obj.phpt new file mode 100644 index 0000000000000..0624482d7bf1b --- /dev/null +++ b/Zend/tests/new_offset_assign_obj.phpt @@ -0,0 +1,13 @@ +--TEST-- +Assigning to a property of a new offset +--FILE-- +bar = 2; + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot use [] for reading in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/readonly_props/variation_nested.phpt b/Zend/tests/readonly_props/variation_nested.phpt index 72a7925da9905..3a65840b47159 100644 --- a/Zend/tests/readonly_props/variation_nested.phpt +++ b/Zend/tests/readonly_props/variation_nested.phpt @@ -70,8 +70,8 @@ Init: 1, op: im: done Init: 1, op: is: 1 Init: 1, op: us: done Init: 0, op: r: Typed property Test::$prop must not be accessed before initialization -Init: 0, op: w: Cannot indirectly modify readonly property Test::$prop +Init: 0, op: w: Typed property Test::$prop must not be accessed before initialization Init: 0, op: rw: Typed property Test::$prop must not be accessed before initialization -Init: 0, op: im: Cannot indirectly modify readonly property Test::$prop +Init: 0, op: im: Typed property Test::$prop must not be accessed before initialization Init: 0, op: is: 0 Init: 0, op: us: done diff --git a/Zend/tests/string_offset_as_object.phpt b/Zend/tests/string_offset_as_object.phpt index 6fdebe936088f..630255d554621 100644 --- a/Zend/tests/string_offset_as_object.phpt +++ b/Zend/tests/string_offset_as_object.phpt @@ -52,12 +52,12 @@ try { ?> --EXPECT-- -Cannot use string offset as an object -Cannot use string offset as an object -Cannot use string offset as an object -Cannot use string offset as an object -Cannot use string offset as an object -Cannot use string offset as an object -Cannot use string offset as an object -Cannot use string offset as an object +Attempt to assign property "bar" on string +Attempt to modify property "bar" on string +Attempt to assign property "bar" on string +Attempt to modify property "bar" on string +Attempt to increment/decrement property "bar" on string +Attempt to increment/decrement property "bar" on string +Attempt to increment/decrement property "bar" on string +Attempt to increment/decrement property "bar" on string Cannot use string offset as an object diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 3334851c4f5a5..c860a3a66cd5f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3022,7 +3022,8 @@ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t zend_separate_if_call_and_write(&var_node, var_ast, type); if (dim_ast == NULL) { - if (type == BP_VAR_R || type == BP_VAR_IS) { + /* Allow BP_VAR_R to support auto-vivification in custom object handlers. */ + if (type == BP_VAR_IS) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading"); } if (type == BP_VAR_UNSET) { @@ -3053,6 +3054,29 @@ static zend_op *zend_compile_dim(znode *result, zend_ast *ast, uint32_t type, bo } /* }}} */ +/* Linear backwards search for OBJ_R/DIM_R fetches, adding the ZEND_FETCH_OBJ_W_CONTAINER flag to them. */ +static void mark_as_obj_w_contaner(zend_op *op) +{ + zend_op *start_op = zend_stack_base(&CG(delayed_oplines_stack)); + + while (true) { + if ((op->opcode != ZEND_FETCH_OBJ_R && op->opcode != ZEND_FETCH_DIM_R)) { + break; + } + op->extended_value |= ZEND_FETCH_OBJ_W_CONTAINER; + if (!(op->op1_type & (IS_VAR|IS_TMP_VAR))) { + break; + } + uint32_t var = op->op1.var; + op--; + if (op < start_op + || !(op->result_type & (IS_VAR|IS_TMP_VAR)) + || op->result.var != var) { + break; + } + } +} + static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { zend_ast *obj_ast = ast->child[0]; @@ -3074,7 +3098,17 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t * check for a nullsafe access. */ } else { zend_short_circuiting_mark_inner(obj_ast); - opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0); + int fetch_mode = type; + /* 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. */ + bool change_fetch_mode = (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_FUNC_ARG); + if (change_fetch_mode) { + fetch_mode = BP_VAR_R; + } + opline = zend_delayed_compile_var(&obj_node, obj_ast, fetch_mode, 0); + if (opline && change_fetch_mode) { + mark_as_obj_w_contaner(opline); + } if (opline && (opline->opcode == ZEND_FETCH_DIM_W || opline->opcode == ZEND_FETCH_DIM_RW || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 0917e481bebf4..fdf2385270335 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -1022,6 +1022,7 @@ ZEND_API zend_string *zend_type_to_string(zend_type type); /* Only one of these can ever be in use */ #define ZEND_FETCH_REF 1 #define ZEND_FETCH_DIM_WRITE 2 +#define ZEND_FETCH_OBJ_W_CONTAINER 3 #define ZEND_FETCH_OBJ_FLAGS 3 /* Used to mark what kind of operation a writing FETCH_DIM is used in, diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 0172106344acd..eb18bd6011094 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2749,7 +2749,7 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z zend_long offset; try_string_offset: - if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { + if (dim_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { switch (Z_TYPE_P(dim)) { case IS_STRING: { @@ -2837,7 +2837,7 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z zend_object *obj = Z_OBJ_P(container); GC_ADDREF(obj); - if (ZEND_CONST_COND(dim_type == IS_CV, 1) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { + if (dim_type == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { dim = ZVAL_UNDEFINED_OP2(); } if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7b7801e7d1c0c..d80f37609cb54 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1005,7 +1005,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; @@ -1018,7 +1018,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 { @@ -1280,7 +1280,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; @@ -1292,7 +1292,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 { @@ -1365,7 +1365,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 { @@ -1899,7 +1899,7 @@ ZEND_VM_HANDLER(176, ZEND_FETCH_STATIC_PROP_IS, ANY, CLASS_FETCH, CACHE_SLOT) ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_IS); } -ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV) +ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV|UNUSED|NEXT, OBJ_W_CONTAINER) { USE_OPLINE zval *container, *dim, *value; @@ -1908,7 +1908,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMP container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP1_TYPE != IS_CONST) { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if (OP2_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { ZEND_VM_C_LABEL(fetch_dim_r_array): value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, OP2_TYPE, BP_VAR_R EXECUTE_DATA_CC); ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); @@ -1921,12 +1921,18 @@ ZEND_VM_C_LABEL(fetch_dim_r_array): } } else { ZEND_VM_C_LABEL(fetch_dim_r_slow): + if (OP2_TYPE == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_DISPATCH_TO_HELPER(zend_use_undef_in_read_context_helper); + } if (OP2_TYPE == 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 { + if (OP2_TYPE == IS_UNUSED) { + ZEND_VM_DISPATCH_TO_HELPER(zend_use_undef_in_read_context_helper); + } zend_fetch_dimension_address_read_R(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); } FREE_OP2(); @@ -2035,7 +2041,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) +ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OBJ_W_CONTAINER|CACHE_SLOT) { USE_OPLINE zval *container; @@ -2069,7 +2075,7 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST zval *retval; if (OP2_TYPE == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -2163,14 +2169,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( @@ -2178,24 +2184,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 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 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(); @@ -2313,7 +2319,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 @@ -2321,7 +2327,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); @@ -2382,7 +2388,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, *value, tmp; @@ -2391,7 +2397,7 @@ ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_ zend_refcounted *garbage = NULL; SAVE_OPLINE(); - object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); + object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -2773,14 +2779,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); @@ -10026,7 +10032,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, ((op->op1_type == IS_CONST) ? !Z_R ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FETCH_DIM_R, (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))), ZEND_FETCH_DIM_R_INDEX, CONST|TMPVAR|CV, CONST|TMPVARCV, SPEC(NO_CONST_CONST)) +ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FETCH_DIM_R, ((op->op2_type != IS_UNDEF) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))), ZEND_FETCH_DIM_R_INDEX, CONST|TMPVAR|CV, CONST|TMPVARCV, SPEC(NO_CONST_CONST)) { USE_OPLINE zval *container, *dim, *value; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 0f89800ec0a89..b4e55cb68eeee 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -6424,7 +6424,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_ container = RT_CONSTANT(opline, opline->op1); dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R EXECUTE_DATA_CC); ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); @@ -6437,12 +6437,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_ } } else { fetch_dim_r_slow: + if (IS_CONST == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } 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); } } else { + if (IS_CONST == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); } @@ -6516,7 +6522,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ zval *retval; if (IS_CONST == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -6730,7 +6736,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)); @@ -8944,7 +8950,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_ container = RT_CONSTANT(opline, opline->op1); dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST != IS_CONST) { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R EXECUTE_DATA_CC); ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); @@ -8957,12 +8963,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_ } } else { fetch_dim_r_slow: + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } if ((IS_TMP_VAR|IS_VAR) == 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 { + 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_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -9036,7 +9048,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -9250,7 +9262,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)); @@ -10285,6 +10297,47 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_UNUSED_HAN } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + dim = NULL; + if (IS_CONST != IS_CONST) { + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_UNUSED, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if (IS_UNUSED == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + if (IS_UNUSED == 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 { + if (IS_UNUSED == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + zend_fetch_dimension_address_read_R(container, dim, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 @@ -10300,7 +10353,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ if (IS_UNUSED == IS_UNUSED) { ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } } @@ -11331,7 +11384,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HAND container = RT_CONSTANT(opline, opline->op1); dim = EX_VAR(opline->op2.var); if (IS_CONST != IS_CONST) { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if (IS_CV != IS_UNUSED && 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); @@ -11344,12 +11397,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HAND } } else { fetch_dim_r_slow: + if (IS_CV == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } 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 { + if (IS_CV == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); } @@ -11423,7 +11482,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ zval *retval; if (IS_CV == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -11637,7 +11696,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)); @@ -15723,6 +15782,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 @@ -15732,7 +15955,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_ container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = RT_CONSTANT(opline, opline->op2); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R EXECUTE_DATA_CC); ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); @@ -15745,12 +15968,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_ } } else { fetch_dim_r_slow: + if (IS_CONST == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } 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); } } else { + if (IS_CONST == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); } @@ -15805,7 +16034,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ zval *retval; if (IS_CONST == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -15899,6 +16128,44 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ 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 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 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 @@ -16011,727 +16278,651 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST 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; - uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_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); +#endif - 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); - GC_ADD_FLAGS(str, flags); - 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); - GC_ADD_FLAGS(str, flags); - 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); - } + 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_NEXT_OPCODE(); + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_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_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; 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(); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; } - op1_str = zval_get_string_func(op1); + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) 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) { - 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(); - } - 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); + if (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); + 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)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } } - 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); + } else { + name = Z_STR_P(RT_CONSTANT(opline, opline->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_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; } } - ZVAL_STR(EX_VAR(opline->result.var), op1_str); - zend_string_release_ex(op2_str, 0); - break; + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } } } - 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); + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { - ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); - 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); + UNDEF_RESULT(); + goto exit_assign_obj; } - } while (0); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + 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)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + 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_INIT_METHOD_CALL_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 *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, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - 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, RT_CONSTANT(opline, opline->op2) 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; - } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - } - zend_throw_error(NULL, "Method name must be a string"); +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (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); + zval *property_val; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } 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 ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - obj = Z_OBJ_P(object); - } else { - do { - if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - obj = Z_OBJ_P(object); + if (UNEXPECTED(prop_info != NULL)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } } else { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - zend_reference *ref = Z_REF_P(object); - - object = &ref->val; - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - obj = Z_OBJ_P(object); - if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else { - Z_ADDREF_P(object); - } + name = Z_STR_P(RT_CONSTANT(opline, opline->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); } - break; + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; } } - 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 (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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); } - HANDLE_EXCEPTION(); + } 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, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + goto exit_assign_obj; } - 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(); } - } while (0); - } - - 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*)); + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); } else { - zend_object *orig_obj = obj; - - if (IS_CONST == IS_CONST) { - function_name = RT_CONSTANT(opline, opline->op2); + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; } + } - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); - if (UNEXPECTED(fbc == NULL)) { - if (EXPECTED(!EG(exception))) { - zend_undefined_method(obj->ce, Z_STR_P(function_name)); - } - - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { - zend_objects_store_del(orig_obj); - } - 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)) { - GC_ADDREF(obj); /* For $this pointer */ - if (GC_DELREF(orig_obj) == 0) { - zend_objects_store_del(orig_obj); - } - } - 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_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); } - if (IS_CONST != IS_CONST) { + 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); } - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { - zend_objects_store_del(obj); - if (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 */ - } - /* 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)) && value) { + 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(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value, *arg; - - if (IS_CONST == IS_CONST) { - SAVE_OPLINE(); - zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - uint32_t arg_num; - arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); - if (UNEXPECTED(!arg)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - } else { - arg = ZEND_CALL_VAR(EX(call), opline->result.var); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); } - value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(arg, value); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); - } - } - 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_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - double d1, d2; + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; - 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)) { - bool 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); + value = _get_zval_ptr_var((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, RT_CONSTANT(opline, opline->op2) 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; - bool result; - zend_ulong hval; - zval *offset; - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = RT_CONSTANT(opline, opline->op2); +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (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); + zval *property_val; - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; - zval *value; - zend_string *str; + 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); -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 (UNEXPECTED(prop_info != NULL)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else { + name = Z_STR_P(RT_CONSTANT(opline, opline->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_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } } - } - value = zend_hash_find_ex(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); + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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, name, 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 (!(opline->extended_value & ZEND_ISEMPTY)) { - result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); } 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; + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; } } - 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; - } + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); } - 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)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } 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; - bool result; + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + 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, RT_CONSTANT(opline, opline->op2) 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); -} - -/* 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; - bool result; +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (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); + zval *property_val; - SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.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); -try_instanceof: - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; + if (UNEXPECTED(prop_info != NULL)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else { + name = Z_STR_P(RT_CONSTANT(opline, opline->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_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } - if (IS_CONST == IS_CONST) { - ce = CACHED_PTR(opline->extended_value); - if (UNEXPECTED(ce == NULL)) { - ce = zend_lookup_class_ex(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 (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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, name, value); + 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)) { - 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; + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; } - result = 0; } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + 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)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + 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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_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_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 = 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 { - SAVE_OPLINE(); - zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - 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_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(); + 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_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_CV_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 { - SAVE_OPLINE(); - zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR|IS_CV) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - 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_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 { - 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(); -} -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); - 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(); + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_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; - 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); - + 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; uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_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); @@ -16739,27 +16930,24 @@ 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 && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); - if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { - zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); - } 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); GC_ADD_FLAGS(str, flags); 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 { @@ -16771,700 +16959,664 @@ 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(); - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { - op2 = ZVAL_UNDEFINED_OP2(); + ZVAL_UNDEFINED_OP1(); } - 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(); + op1_str = zval_get_string_func(op1); } -} - -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_NONE(); - } else { -is_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_NONE(); - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = (double)Z_LVAL_P(op1); - d2 = Z_DVAL_P(op2); - goto is_equal_double; + 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(); } - } 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; + 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; } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - d1 = Z_DVAL_P(op1); - d2 = (double)Z_LVAL_P(op2); - goto is_equal_double; } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op1); - } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op2); - } - if (result) { - goto is_equal_true; - } else { - goto is_equal_false; + 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; } } - } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - double d1, d2; + 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); - 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_JMPZ(); - } else { -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_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; - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - d1 = Z_DVAL_P(op1); - d2 = (double)Z_LVAL_P(op2); - goto is_equal_double; + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release_ex(op1_str, 0); } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op1); - } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op2); - } - if (result) { - goto is_equal_true; - } else { - goto is_equal_false; - } + if (IS_CONST != IS_CONST) { + zend_string_release_ex(op2_str, 0); } - } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + } 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_JMPNZ_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_JMPNZ(); - } else { -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_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; + SAVE_OPLINE(); + + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_CONST != IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); } else { - goto is_equal_false; + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(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); + } + + 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)) { - bool 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); + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op2); + + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); } - if (result) { - goto is_equal_true; - } else { - goto is_equal_false; + 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)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); } } + 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_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) -{ - USE_OPLINE - zval *op1, *op2; - double d1, d2; + if (IS_CONST != IS_CONST) { - 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_NONE(); - } else { -is_not_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_NONE(); - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = (double)Z_LVAL_P(op1); - d2 = Z_DVAL_P(op2); - goto is_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; + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - d1 = Z_DVAL_P(op1); - d2 = (double)Z_LVAL_P(op2); - goto is_not_equal_double; } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - bool 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; - } + /* 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 */ } + /* 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_not_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_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - double d1, d2; + zval *value, *arg; - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { - /* pass */ - } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { -is_not_equal_true: - ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - } else { -is_not_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = (double)Z_LVAL_P(op1); - d2 = Z_DVAL_P(op2); - goto is_not_equal_double; - } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { - d1 = Z_DVAL_P(op1); - d2 = Z_DVAL_P(op2); -is_not_equal_double: - if (d1 != d2) { - goto is_not_equal_true; - } else { - goto is_not_equal_false; - } - } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { - d1 = Z_DVAL_P(op1); - d2 = (double)Z_LVAL_P(op2); - goto is_not_equal_double; + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - bool 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; - } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_NEXT_OPCODE(); } -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_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_not_equal_true: - ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +case_true: + ZEND_VM_SMART_BRANCH_TRUE(); } else { -is_not_equal_false: - ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); +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_not_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_not_equal_double: - if (d1 != d2) { - goto is_not_equal_true; +case_double: + if (d1 == d2) { + goto case_true; } else { - goto is_not_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_not_equal_double; + goto case_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { bool 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; + + if (result) { + goto case_true; } else { - goto is_not_equal_false; + goto case_false; } } } - ZEND_VM_TAIL_CALL(zend_is_not_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_SPACESHIP_SPEC_TMPVAR_TMPVAR_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; + zval *container; + bool result; + zend_ulong hval; + zval *offset; 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(); -} + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = RT_CONSTANT(opline, opline->op2); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; - 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(); -} +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(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; + } + } -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; + 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); - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - 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_TMP_VAR|IS_VAR), BP_VAR_R EXECUTE_DATA_CC); - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto fetch_dim_r_array; - } else { - goto fetch_dim_r_slow; + if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { + /* avoid exception check */ + + ZEND_VM_SMART_BRANCH(result, 0); } } else { -fetch_dim_r_slow: - if ((IS_TMP_VAR|IS_VAR) == 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 = (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 { - zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); } - 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_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; +isset_dim_obj_exit: - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_read_IS(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)); 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_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; - void **cache_slot = NULL; + 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))) { - do { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - break; - } - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + if (((IS_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; } - zend_wrong_property_read(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); - ZVAL_NULL(EX_VAR(opline->result.var)); - goto fetch_obj_r_finish; - } while (0); + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } } - /* here we are sure we are dealing with an object */ - do { - zend_object *zobj = Z_OBJ_P(container); - zend_string *name, *tmp_name; - zval *retval; + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + 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 (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } - 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)) { - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); - if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { - uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); +isset_object_finish: - if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { - Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} - if (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_known_hash(zobj->properties, name); - 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; - } - } - } - } - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); - } else { - name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - break; - } - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE -#if ZEND_DEBUG - /* For non-standard object handlers, verify a declared property type in debug builds. - * Fetch prop_info before calling read_property(), as it may deallocate the object. */ - zend_property_info *prop_info = NULL; - if (zobj->handlers->read_property != zend_std_read_property) { - prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); - } -#endif - retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); -#if ZEND_DEBUG - if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO - && ZEND_TYPE_IS_SET(prop_info->type)) { - ZVAL_OPT_DEREF(retval); - zend_verify_property_type(prop_info, retval, /* strict */ true); - } -#endif + zval *key, *subject; + HashTable *ht; + bool result; - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } + SAVE_OPLINE(); - 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); + 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; + } } - } while (0); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } -fetch_obj_r_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_OBJ_IS_SPEC_TMPVAR_TMPVAR_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_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - void **cache_slot = NULL; + zval *expr; + bool result; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + 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_CONST == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_lookup_class_ex(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 && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { - ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } - ZVAL_NULL(EX_VAR(opline->result.var)); - goto fetch_obj_is_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_TMP_VAR|IS_VAR) == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value); +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + zend_long offset; + HashTable *ht; - if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { - uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + 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 { + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + 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(); + } - 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)) { - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); - if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { - uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); +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(); +} - if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { - Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); +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; - if (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_known_hash(zobj->properties, name); - 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; - } - } - } - } - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + 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 { - name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - break; - } + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR|IS_CV) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } - - retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); - - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); + 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(); } - - 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); + } 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; } - } while (0); + } 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_obj_is_finish: - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); +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_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - zend_string *op1_str, *op2_str, *str; + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + 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); @@ -17494,6 +17646,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { + zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); + } 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); GC_ADD_FLAGS(str, flags); @@ -17515,228 +17670,139 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR } } ZEND_VM_NEXT_OPCODE(); - } - - SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - op1_str = Z_STR_P(op1); - } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - op1_str = zend_string_copy(Z_STR_P(op1)); } else { + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + op1 = ZVAL_UNDEFINED_OP1(); } - op1_str = zval_get_string_func(op1); - } - if ((IS_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 = ZVAL_UNDEFINED_OP2(); } - op2_str = zval_get_string_func(op2); + concat_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } - do { - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if ((IS_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; +} + +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_NONE(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; } - 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; + } 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; } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; } - 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); - - ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); - 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); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } } - } 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(); + } + 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_INIT_METHOD_CALL_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 *function_name; - zval *object; - zend_function *fbc; - zend_class_entry *called_scope; - zend_object *obj; - zend_execute_data *call; - uint32_t call_info; - - SAVE_OPLINE(); - - object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if ((IS_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_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); - } + zval *op1, *op2; + double d1, d2; - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - obj = Z_OBJ_P(object); - } else { - do { - if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - obj = Z_OBJ_P(object); + 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_JMPZ(); } else { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - zend_reference *ref = Z_REF_P(object); - - object = &ref->val; - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - obj = Z_OBJ_P(object); - if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else { - Z_ADDREF_P(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(); +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); } - } while (0); - } - - called_scope = obj->ce; - - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); - } else { - zend_object *orig_obj = obj; - - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; } - - /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_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)); - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { - zend_objects_store_del(orig_obj); + } 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; } - 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); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; } - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - GC_ADDREF(obj); /* For $this pointer */ - if (GC_DELREF(orig_obj) == 0) { - zend_objects_store_del(orig_obj); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool 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 (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)); - } - - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { - zend_objects_store_del(obj); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; } } - /* 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 */ - } - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } - - call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, obj); - call->prev_execute_data = EX(call); - EX(call) = call; - - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17744,839 +17810,644 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLE 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 (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { -case_true: - ZEND_VM_SMART_BRANCH_TRUE(); +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); } else { -case_false: - ZEND_VM_SMART_BRANCH_FALSE(); +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 case_double; + goto is_equal_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = Z_DVAL_P(op1); d2 = Z_DVAL_P(op2); -case_double: +is_equal_double: if (d1 == d2) { - goto case_true; + goto is_equal_true; } else { - goto case_false; + goto is_equal_false; } } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { d1 = Z_DVAL_P(op1); d2 = (double)Z_LVAL_P(op2); - goto case_double; + goto is_equal_double; } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } if (result) { - goto case_true; + goto is_equal_true; } else { - goto case_false; + goto is_equal_false; } } } - ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_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 *container; - bool 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; + zval *op1, *op2; + double d1, d2; -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(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; + 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_NONE(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; } - - 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 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 { - result = (value == NULL || !i_zend_is_true(value)); + } 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 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; + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool 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; + } } } - - 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); + 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_ISSET_ISEMPTY_PROP_OBJ_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 *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); + zval *op1, *op2; + double d1, d2; - 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; + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); } - } else { - result = (opline->extended_value & ZEND_ISEMPTY); - goto isset_object_finish; + } 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; } - } - - 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)) { - result = 0; - goto isset_object_finish; + } 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)) { + bool 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; + } } } - - 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_SMART_BRANCH(result, 1); + 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_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *op1, *op2; + double d1, d2; - zval *key, *subject; - HashTable *ht; - bool result; - - SAVE_OPLINE(); - - 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; + 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)) { + bool 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_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_SMART_BRANCH(result, 1); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; - bool result; + zval *op1, *op2; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + 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(); +} -try_instanceof: - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; - if (IS_VAR == IS_CONST) { - ce = CACHED_PTR(opline->extended_value); - if (UNEXPECTED(ce == NULL)) { - ce = zend_lookup_class_ex(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); - if (EXPECTED(ce)) { - CACHE_PTR(opline->extended_value, ce); - } - } - } else if (IS_VAR == IS_UNUSED) { - ce = zend_fetch_class(NULL, opline->op2.num); - if (UNEXPECTED(ce == NULL)) { - 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; - } + 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)); - ZEND_VM_SMART_BRANCH(result, 1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varname; - zval *retval; + zval *object; + zval *property; + zval *value; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; zend_string *name, *tmp_name; - HashTable *target_symbol_table; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + object = _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) { - 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)) { - if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - 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); + 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; } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + 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 (type == BP_VAR_W) { - retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); - } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { - retval = &EG(uninitialized_zval); + +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 { - if ((IS_TMP_VAR|IS_VAR) == IS_CV) { - /* Keep name alive in case an error handler tries to free it. */ - zend_string_addref(name); - } - zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", - (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); - if (type == BP_VAR_RW && !EG(exception)) { - retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); - } else { - retval = &EG(uninitialized_zval); - } - if ((IS_TMP_VAR|IS_VAR) == IS_CV) { - zend_string_release(name); + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; } } - /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ - } else if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); - if (Z_TYPE_P(retval) == IS_UNDEF) { - if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { - goto fetch_this; - } - if (type == BP_VAR_W) { - ZVAL_NULL(retval); - } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { - retval = &EG(uninitialized_zval); - } else { - zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", - (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); - if (type == BP_VAR_RW && !EG(exception)) { - ZVAL_NULL(retval); - } else { - retval = &EG(uninitialized_zval); + 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; - if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } + 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) { - zend_tmp_string_release(tmp_name); - } + 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); - 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(); -} + 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); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_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_TMPVAR_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)); -} + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -} + SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - int fetch_type = - (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? - BP_VAR_W : BP_VAR_R; - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(fetch_type ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -} + 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; + } -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)); -} +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); -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)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value, *arg; + zval *container, *dim, *value; - if (IS_UNUSED == IS_CONST) { - SAVE_OPLINE(); - zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - uint32_t arg_num; - arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); - if (UNEXPECTED(!arg)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + if ((IS_TMP_VAR|IS_VAR) == 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 { - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - } - - value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(arg, value); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); + 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_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } - 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_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varname; - zend_string *name, *tmp_name; - HashTable *target_symbol_table; + zval *container; SAVE_OPLINE(); - - varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - name = Z_STR_P(varname); - } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { - name = Z_STR_P(varname); - tmp_name = NULL; - } else { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { - varname = ZVAL_UNDEFINED_OP1(); - } - name = zval_try_get_tmp_string(varname, &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - } - - 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); - } + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_read_IS(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)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - /* Should be bool result? as below got: result = (opline->extended_value & ZEND_ISEMPTY) */ - int result; - zval *varname; - zend_string *name, *tmp_name; - HashTable *target_symbol_table; + zval *container; + void **cache_slot = NULL; 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); - - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + container = _get_zval_ptr_var(opline->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 ((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; + } } - result = Z_TYPE_P(value) > IS_NULL; - } else { - result = !i_zend_is_true(value); - } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); } - ZEND_VM_SMART_BRANCH(result, 1); -} + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; -/* 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 *expr; - bool result; + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* FUNC_ARG fetch may contain it */); - SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); -try_instanceof: - if (Z_TYPE_P(expr) == IS_OBJECT) { - zend_class_entry *ce; + 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)) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); - if (IS_UNUSED == IS_CONST) { - ce = CACHED_PTR(opline->extended_value); - if (UNEXPECTED(ce == NULL)) { - ce = zend_lookup_class_ex(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 (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); + + if (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_known_hash(zobj->properties, name); + 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_UNUSED == IS_UNUSED) { - ce = zend_fetch_class(NULL, opline->op2.num); - if (UNEXPECTED(ce == NULL)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); + break; } - } 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 ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); } - result = 0; - } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; - zend_long count; + zval *property, *container, *result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - while (1) { - if (Z_TYPE_P(op1) == IS_ARRAY) { - count = zend_hash_num_elements(Z_ARRVAL_P(op1)); - break; - } else if (Z_TYPE_P(op1) == IS_OBJECT) { - zend_object *zobj = Z_OBJ_P(op1); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + 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 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(); +} - /* first, we check if the handler is defined */ - if (zobj->handlers->count_elements) { - if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { - break; - } - if (UNEXPECTED(EG(exception))) { - count = 0; - break; - } - } - - /* if not and the object implements Countable we call its count() method */ - if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { - zval retval; - - zend_function *count_fn = zend_hash_find_ptr(&zobj->ce->function_table, ZSTR_KNOWN(ZEND_STR_COUNT)); - zend_call_known_instance_method_with_0_params(count_fn, zobj, &retval); - count = zval_get_long(&retval); - zval_ptr_dtor(&retval); - break; - } - - /* If There's no handler and it doesn't implement Countable then emit a TypeError */ - } 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(); - } - count = 0; - zend_type_error("%s(): Argument #1 ($value) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_value_name(op1)); - break; - } - - ZVAL_LONG(EX_VAR(opline->result.var), count); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_array *ht = Z_ARRVAL_P(_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)); - ZVAL_LONG(EX_VAR(opline->result.var), zend_hash_num_elements(ht)); - if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR) && !(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { - SAVE_OPLINE(); - zend_array_destroy(ht); - if (EG(exception)) { - HANDLE_EXCEPTION(); - } - } - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - SAVE_OPLINE(); - if (UNEXPECTED(!EX(func)->common.scope)) { - zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } else { - zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated"); - ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - 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_zval_value_name(op1)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - } - break; - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zval *result = EX_VAR(opline->result.var); - ZVAL_COPY(result, value); - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - - 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; - uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_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); - - if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { - zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); - } - 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); - GC_ADD_FLAGS(str, flags); - 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); - GC_ADD_FLAGS(str, flags); - 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(); - } else { - SAVE_OPLINE(); - - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - op1 = ZVAL_UNDEFINED_OP1(); - } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { - op2 = ZVAL_UNDEFINED_OP2(); - } - concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; + zval *property, *container, *result; SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - dim = EX_VAR(opline->op2.var); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { -fetch_dim_r_array: - value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R EXECUTE_DATA_CC); - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto fetch_dim_r_array; - } else { - goto fetch_dim_r_slow; - } - } else { -fetch_dim_r_slow: - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); - } - } else { - zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); + 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 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); } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -18594,12 +18465,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN break; } } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(container, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); ZVAL_NULL(EX_VAR(opline->result.var)); - goto fetch_obj_r_finish; + goto fetch_obj_is_finish; } while (0); } @@ -18609,25 +18479,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN zend_string *name, *tmp_name; zval *retval; - if (IS_CV == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + 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_INFO_P(retval) != IS_UNDEF)) { + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { - goto fetch_obj_r_copy; + goto fetch_obj_is_copy; } else { -fetch_obj_r_fast_copy: +fetch_obj_is_fast_copy: ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); ZEND_VM_NEXT_OPCODE(); } } } else if (EXPECTED(zobj->properties != NULL)) { - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); @@ -18640,9 +18510,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN 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; + goto fetch_obj_is_copy; } else { - goto fetch_obj_r_fast_copy; + goto fetch_obj_is_fast_copy; } } } @@ -18653,170 +18523,670 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN 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; + goto fetch_obj_is_copy; } else { - goto fetch_obj_r_fast_copy; + goto fetch_obj_is_fast_copy; } } } } - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); } else { - name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); break; } } -#if ZEND_DEBUG - /* For non-standard object handlers, verify a declared property type in debug builds. - * Fetch prop_info before calling read_property(), as it may deallocate the object. */ - zend_property_info *prop_info = NULL; - if (zobj->handlers->read_property != zend_std_read_property) { - prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); - } -#endif - retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); -#if ZEND_DEBUG - if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO - && ZEND_TYPE_IS_SET(prop_info->type)) { - ZVAL_OPT_DEREF(retval); - zend_verify_property_type(prop_info, retval, /* strict */ true); - } -#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); - if (IS_CV != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_tmp_string_release(tmp_name); } if (retval != EX_VAR(opline->result.var)) { -fetch_obj_r_copy: +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_r_finish: - +fetch_obj_is_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(); } -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_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 USE_OPLINE - zval *container; - void **cache_slot = NULL; +#endif + + 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_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || - ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - break; - } - } - if (IS_CV == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { - ZVAL_UNDEFINED_OP2(); - } - ZVAL_NULL(EX_VAR(opline->result.var)); - goto fetch_obj_is_finish; - } while (0); + 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, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } - /* 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) { - cache_slot = CACHE_ADDR(opline->extended_value); +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (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); + zval *property_val; - 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))) { + 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(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(); + if (UNEXPECTED(prop_info != NULL)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + goto exit_assign_obj; } - } else if (EXPECTED(zobj->properties != NULL)) { - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); - 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); + } + } else { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } - if (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; + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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 { - goto fetch_obj_is_fast_copy; + 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); } - CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); - } - retval = zend_hash_find_known_hash(zobj->properties, name); - 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; } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + goto exit_assign_obj; } } - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); - } else { - name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - break; - } } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { - retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); - - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); + UNDEF_RESULT(); + goto exit_assign_obj; } + } - 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); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } -fetch_obj_is_finish: + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + 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)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + 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_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.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, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) 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) { + if (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); + 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)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + 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)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + 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_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) 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) { + if (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); + 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)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + 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)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + 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_TMPVAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.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_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) 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) { + if (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); + 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)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + 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)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + 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_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + 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 { + 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); + } + + 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|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 *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_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 { + 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); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* 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, *op2; @@ -18824,16 +19194,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - op2 = EX_VAR(opline->op2.var); + 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_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { zend_string *op1_str = Z_STR_P(op1); zend_string *op2_str = Z_STR_P(op2); zend_string *str; uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if (IS_CV == IS_CONST || IS_CV == IS_CV) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); @@ -18841,13 +19211,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN 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)) { + } 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_CV & (IS_TMP_VAR|IS_VAR)) { + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && @@ -18858,7 +19228,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); GC_ADD_FLAGS(str, flags); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } else { @@ -18870,7 +19240,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN 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)) { + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zend_string_release_ex(op2_str, 0); } } @@ -18888,12 +19258,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN } op1_str = zval_get_string_func(op1); } - if (IS_CV == IS_CONST) { + 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_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + 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); @@ -18901,7 +19271,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN do { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { - if (IS_CV == IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { GC_ADDREF(op2_str); } @@ -18911,7 +19281,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN break; } } - if (IS_CV != IS_CONST) { + 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))) { @@ -18932,16 +19302,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_string_release_ex(op1_str, 0); } - if (IS_CV != IS_CONST) { + 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_CV_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; @@ -18956,19 +19326,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C 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_TMP_VAR|IS_VAR) != IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } - if (IS_CV != IS_CONST && + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { - if ((IS_CV & (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_CV == 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)) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -18976,7 +19346,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } } 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); @@ -19008,17 +19378,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C 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) { - + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } HANDLE_EXCEPTION(); } } - if (IS_CV == IS_CONST) { - function_name = EX_VAR(opline->op2.var); + 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(); } @@ -19027,29 +19397,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C called_scope = obj->ce; - if (IS_CV == IS_CONST && + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { zend_object *orig_obj = obj; - if (IS_CV == IS_CONST) { - function_name = EX_VAR(opline->op2.var); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } /* First, locate the function. */ - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + 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)); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { zend_objects_store_del(orig_obj); } HANDLE_EXCEPTION(); } - if (IS_CV == IS_CONST && + 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); @@ -19065,8 +19435,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } } - if (IS_CV != IS_CONST) { - + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -19096,14 +19466,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C 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_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); + 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))) { @@ -19136,7 +19506,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZE } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { bool 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 { @@ -19147,7 +19517,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZE 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_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -19157,7 +19527,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = EX_VAR(opline->op2.var); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -19169,17 +19539,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (ZEND_HANDLE_NUMERIC(str, hval)) { goto num_index_prop; } } - value = zend_hash_find_ex(ht, str, IS_CV == IS_CONST); + value = zend_hash_find_ex(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_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + } 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 { @@ -19197,7 +19567,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP 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 { @@ -19211,7 +19581,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP } } - if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -19221,12 +19591,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP } 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_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; @@ -19236,7 +19606,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.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))) { @@ -19252,7 +19622,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } - if (IS_CV == IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { name = Z_STR_P(offset); } else { name = zval_try_get_tmp_string(offset, &tmp_name); @@ -19264,19 +19634,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); - if (IS_CV != IS_CONST) { + 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_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_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 @@ -19287,14 +19657,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_C SAVE_OPLINE(); key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - subject = EX_VAR(opline->op2.var); + 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_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + 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; @@ -19304,2710 +19674,2278 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_C result = 0; } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ -static ZEND_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_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *retval_ptr; - zval *return_value; + zval *expr; + bool result; - retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - return_value = EX(return_value); + SAVE_OPLINE(); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - 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_CALL_OBSERVED)))) { - zend_refcounted *ref = Z_COUNTED_P(retval_ptr); - ZVAL_COPY_VALUE(return_value, retval_ptr); - if (GC_MAY_LEAK(ref)) { - SAVE_OPLINE(); - 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); +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; - 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); + if (IS_VAR == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_lookup_class_ex(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 { - ZVAL_COPY_VALUE(return_value, retval_ptr); } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + 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; } - - - - ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +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 *retval_ptr; - zval *return_value; + 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); - return_value = EX(return_value); - - 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 (!return_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; + } 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)) { + if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { 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(return_value, retval_ptr); - break; - } - - ZVAL_NEW_REF(return_value, retval_ptr); - if (IS_TMP_VAR == IS_CONST) { - Z_TRY_ADDREF_P(retval_ptr); - } } - break; + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } + } - retval_ptr = zend_get_bad_ptr(); - - 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 (return_value) { - ZVAL_NEW_REF(return_value, retval_ptr); - } else { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } - break; + 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 (return_value) { - if (Z_ISREF_P(retval_ptr)) { - Z_ADDREF_P(retval_ptr); + if (type == BP_VAR_W) { + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { + retval = &EG(uninitialized_zval); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); + if (type == BP_VAR_RW && !EG(exception)) { + retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { - ZVAL_MAKE_REF_EX(retval_ptr, 2); + retval = &EG(uninitialized_zval); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + zend_string_release(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 || type == BP_VAR_UNSET) { + retval = &EG(uninitialized_zval); + } else { + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); + if (type == BP_VAR_RW && !EG(exception)) { + ZVAL_NULL(retval); + } else { + retval = &EG(uninitialized_zval); + } } - ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } + } + if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } while (0); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } - ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + 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_GENERATOR_RETURN_SPEC_TMP_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 *retval; + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_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(); - retval = _get_zval_ptr_tmp(opline->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)); +} - /* Copy return value into generator->retval */ - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { - ZVAL_COPY_VALUE(&generator->retval, retval); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { - Z_ADDREF(generator->retval); - } - } - } else if (IS_TMP_VAR == IS_CV) { - ZVAL_COPY_DEREF(&generator->retval, retval); - } else /* if (IS_TMP_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(retval))) { - zend_refcounted *ref = Z_COUNTED_P(retval); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_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)); +} - 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); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = NULL; + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_UNUSED, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; } } else { - ZVAL_COPY_VALUE(&generator->retval, retval); +fetch_dim_r_slow: + if (IS_UNUSED == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + if (IS_UNUSED == 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 { + if (IS_UNUSED == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + zend_fetch_dimension_address_read_R(container, dim, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); } - EG(current_execute_data) = EX(prev_execute_data); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - /* Close the generator to free up resources */ - zend_generator_close(generator, 1); +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; - /* Pass execution back to handling code */ - ZEND_VM_RETURN(); + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if ((IS_TMP_VAR|IS_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_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *arg, *param; + zval *varname; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; SAVE_OPLINE(); - arg = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - param = ZEND_CALL_VAR(EX(call), opline->result.var); - 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); - Z_TRY_ADDREF_P(arg); - ZVAL_NEW_REF(param, arg); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + tmp_name = NULL; } else { - ZVAL_COPY(param, arg); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = ZVAL_UNDEFINED_OP1(); + } + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } } + 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_CAST_SPEC_TMP_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 *expr; - zval *result = EX_VAR(opline->result.var); - HashTable *ht; + zval *value; + /* Should be bool result? as below got: result = (opline->extended_value & ZEND_ISEMPTY) */ + int result; + zval *varname; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + 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); + } - 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); - } + 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); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - 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 if (Z_OBJ_P(expr)->properties == NULL - && Z_OBJ_HT_P(expr)->get_properties_for == NULL - && Z_OBJ_HT_P(expr)->get_properties == zend_std_get_properties) { - /* Optimized version without rebuilding properties HashTable */ - ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr))); - } 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 (!value) { + result = (opline->extended_value & ZEND_ISEMPTY); + } else { + if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + if (Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); } + result = Z_TYPE_P(value) > IS_NULL; + } else { + result = !i_zend_is_true(value); + } } - 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_FE_RESET_R_SPEC_TMP_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 *array_ptr, *result; + zval *expr; + bool result; SAVE_OPLINE(); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - 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; +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; - ZEND_VM_NEXT_OPCODE(); - } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - zend_object *zobj = Z_OBJ_P(array_ptr); - if (!zobj->ce->get_iterator) { - HashTable *properties = 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); + if (IS_UNUSED == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_lookup_class_ex(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 { - properties = zobj->handlers->get_properties(zobj); - } - - result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); - if (IS_TMP_VAR != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); - } - - if (zend_hash_num_elements(properties) == 0) { - Z_FE_ITER_P(result) = (uint32_t) -1; - - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } - - Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - 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))) { + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + 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(); } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); } + result = ce && instanceof_function(Z_OBJCE_P(expr), ce); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { + expr = Z_REFVAL_P(expr); + goto try_instanceof; } else { - zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(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)); + 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_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref; + zval *op1; + zend_long count; SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { - array_ref = array_ptr = zend_get_bad_ptr(); - if (Z_ISREF_P(array_ref)) { - array_ptr = Z_REFVAL_P(array_ref); - } - } else { - array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - } - - if (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); + while (1) { + if (Z_TYPE_P(op1) == IS_ARRAY) { + count = zend_hash_num_elements(Z_ARRVAL_P(op1)); + break; + } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); - 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) { - HashTable *properties; - 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); + /* first, we check if the handler is defined */ + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { + break; } - 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); + if (UNEXPECTED(EG(exception))) { + count = 0; + break; } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); - } - - properties = Z_OBJPROP_P(array_ptr); - if (zend_hash_num_elements(properties) == 0) { - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1; - - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + /* 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_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - bool is_empty = zend_fe_reset_iterator(array_ptr, 1 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_function *count_fn = zend_hash_find_ptr(&zobj->ce->function_table, ZSTR_KNOWN(ZEND_STR_COUNT)); + zend_call_known_instance_method_with_0_params(count_fn, zobj, &retval); + count = zval_get_long(&retval); + zval_ptr_dtor(&retval); + break; } - } - } else { - zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(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_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; - zend_reference *ref = NULL; - bool 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 = Z_REF_P(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) { - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(result); - } + /* If There's no handler and it doesn't implement Countable then emit a TypeError */ + } 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_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + count = 0; + zend_type_error("%s(): Argument #1 ($value) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_value_name(op1)); + break; } + ZVAL_LONG(EX_VAR(opline->result.var), count); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; - zend_reference *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 = Z_REF_P(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) { - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, 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 ((IS_TMP_VAR & IS_VAR) && ref) { - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); + zend_array *ht = Z_ARRVAL_P(_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)); + ZVAL_LONG(EX_VAR(opline->result.var), zend_hash_num_elements(ht)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR) && !(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + SAVE_OPLINE(); + zend_array_destroy(ht); + if (EG(exception)) { + HANDLE_EXCEPTION(); } } ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val, *result; - - val = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (Z_TYPE_P(val) > IS_NULL) { - do { - if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) { - val = Z_REFVAL_P(val); - if (Z_TYPE_P(val) <= IS_NULL) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - break; - } - } - ZEND_VM_NEXT_OPCODE(); - } while (0); - } - - result = EX_VAR(opline->result.var); - uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK; - if (EXPECTED(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) { - ZVAL_NULL(result); - if (IS_TMP_VAR == IS_CV - && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF) - && (opline->extended_value & ZEND_JMP_NULL_BP_VAR_IS) == 0 - ) { - SAVE_OPLINE(); - ZVAL_UNDEFINED_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + SAVE_OPLINE(); + if (UNEXPECTED(!EX(func)->common.scope)) { + zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } else { + zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated"); + ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); + if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } - } else if (short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) { - ZVAL_FALSE(result); } else { - ZEND_ASSERT(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY); - ZVAL_TRUE(result); - } - - ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); -} - -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); + zval *op1; - 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); + 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_zval_value_name(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_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - 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); + 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_STRICT_SPEC_TMP_CONST_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; - 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); + 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); + div_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_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - 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); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + pow_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 USE_OPLINE -#endif + zval *op1, *op2; - 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)); - } -} + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = EX_VAR(opline->op2.var); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif + if (((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; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); - 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)); + 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); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { + zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); + } + 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); + GC_ADD_FLAGS(str, flags); + 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); + GC_ADD_FLAGS(str, flags); + 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_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_NEXT_OPCODE(); } else { - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + SAVE_OPLINE(); + + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); + } + concat_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; - zval *var; + zval *op1, *op2; - /* 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); + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + compare_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - } - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_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 - zend_string **rope; - zval *var, *ret; - uint32_t i; + zval *object; + zval *property; + zval *value; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; - rope = (zend_string**)EX_VAR(opline->op1.var); - if (IS_CONST == IS_CONST) { - var = RT_CONSTANT(opline, opline->op2); - rope[opline->extended_value] = Z_STR_P(var); - if (UNEXPECTED(Z_REFCOUNTED_P(var))) { - Z_ADDREF_P(var); - } - } else { - var = RT_CONSTANT(opline, opline->op2); - if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { - if (IS_CONST == IS_CV) { - rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); - } else { - rope[opline->extended_value] = Z_STR_P(var); + SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + 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_CV == IS_CONST) { + name = Z_STR_P(property); } else { - SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; } - rope[opline->extended_value] = zval_get_string_func(var); + } + 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; - if (UNEXPECTED(EG(exception))) { - for (i = 0; i <= opline->extended_value; i++) { - zend_string_release_ex(rope[i], 0); + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + if (IS_CV == IS_CONST) { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + } else { + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr); + } + if (UNEXPECTED(prop_info)) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); } - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); } - } - - size_t len = 0; - uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES; - for (i = 0; i <= opline->extended_value; i++) { - flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]); - len += ZSTR_LEN(rope[i]); - } - ret = EX_VAR(opline->result.var); - ZVAL_STR(ret, zend_string_alloc(len, 0)); - GC_ADD_FLAGS(Z_STR_P(ret), flags); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); - char *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'; + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - 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_SEND_VAL_EX_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value, *arg; - uint32_t arg_num; + zval *object; + zval *property; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; - if (IS_CONST == IS_CONST) { - SAVE_OPLINE(); - zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); - if (UNEXPECTED(!arg)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_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); + + 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; } - } else { - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - arg_num = opline->op2.num; - } - if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { - if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_val_by_ref; +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } } - } else if (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(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(arg, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); + 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); } - } - ZEND_VM_NEXT_OPCODE(); + 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_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_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 *expr_ptr, new_expr; + zval *container, *dim, *value; SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = zend_get_bad_ptr(); - if (Z_ISREF_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); + 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 (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } } else { - ZVAL_MAKE_REF_EX(expr_ptr, 2); - } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.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); - } +fetch_dim_r_slow: + if (IS_CV == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - } - } - - if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); - zend_string *str; - zend_ulong hval; - -add_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; } -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_safe(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_array_offset_access(offset); - zval_ptr_dtor_nogc(expr_ptr); + zend_fetch_dimension_address_read_R_slow(container, dim 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); + if (IS_CV == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; USE_OPLINE + zval *container; - array = EX_VAR(opline->result.var); - if (IS_TMP_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - ZVAL_ARR(array, zend_new_array(size)); - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init_mixed(Z_ARRVAL_P(array)); - } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); - } + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *container; + void **cache_slot = NULL; SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + do { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); + /* 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; - /* Set the new yielded value */ - if (IS_TMP_VAR != IS_UNUSED) { - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { - zval *value; + if (IS_CV == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* FUNC_ARG fetch may contain it */); - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - 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 (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 { - zval *value_ptr = zend_get_bad_ptr(); + } else if (EXPECTED(zobj->properties != NULL)) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); - /* 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 (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); + + if (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); } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); + retval = zend_hash_find_known_hash(zobj->properties, name); + 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; + } } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var 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)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; } } - } 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); +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); } - 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); +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); } - } 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_IN_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1; - HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); - zval *result; +#endif - 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); - if (IS_TMP_VAR & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op1); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } - ZEND_VM_SMART_BRANCH(result, 0); - } - if (opline->extended_value) { - if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { - result = zend_hash_index_find(ht, Z_LVAL_P(op1)); - ZEND_VM_SMART_BRANCH(result, 0); - } - SAVE_OPLINE(); - if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { - op1 = Z_REFVAL_P(op1); - if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - result = zend_hash_find(ht, Z_STR_P(op1)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 0); - } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { - result = zend_hash_index_find(ht, Z_LVAL_P(op1)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 0); - } - } else if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - } else if (Z_TYPE_P(op1) <= IS_FALSE) { - if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - SAVE_OPLINE(); - ZVAL_UNDEFINED_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + 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); } - result = zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC()); - ZEND_VM_SMART_BRANCH(result, 0); - } else { - zend_string *key; - zval key_tmp; + } while (0); - if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { - op1 = Z_REFVAL_P(op1); - if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - result = zend_hash_find(ht, Z_STR_P(op1)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 0); - } - } +fetch_obj_r_finish: - SAVE_OPLINE(); - ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { - ZVAL_STR(&key_tmp, key); - if (zend_compare(op1, &key_tmp) == 0) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(1, 1); - } - } ZEND_HASH_FOREACH_END(); - } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(0, 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_FETCH_OBJ_W_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 USE_OPLINE -#endif + zval *property, *container, *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_TMP_VAR|IS_VAR) == IS_UNUSED) { - ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } -} + SAVE_OPLINE(); -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 + 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 OPLINE_CC 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_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + 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_ROPE_ADD_SPEC_TMP_TMPVAR_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 - zend_string **rope; - zval *var; + zval *property, *container, *result; - /* 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(); - } + 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 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_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_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 - zend_string **rope; - zval *var, *ret; - uint32_t i; + zval *container; + void **cache_slot = NULL; - rope = (zend_string**)EX_VAR(opline->op1.var); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - rope[opline->extended_value] = Z_STR_P(var); - if (UNEXPECTED(Z_REFCOUNTED_P(var))) { - Z_ADDREF_P(var); - } - } else { - var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV) { - rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); - } else { - rope[opline->extended_value] = Z_STR_P(var); + SAVE_OPLINE(); + container = _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; + } } - } else { - SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + if (IS_CV == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.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(); - } - } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); } - size_t len = 0; - uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES; - for (i = 0; i <= opline->extended_value; i++) { - flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]); - len += ZSTR_LEN(rope[i]); - } - ret = EX_VAR(opline->result.var); - ZVAL_STR(ret, zend_string_alloc(len, 0)); - GC_ADD_FLAGS(Z_STR_P(ret), flags); + /* 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; - char *target = Z_STRVAL_P(ret); - for (i = 0; i <= opline->extended_value; i++) { - memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); - target += ZSTR_LEN(rope[i]); - zend_string_release_ex(rope[i], 0); - } - *target = '\0'; + if (IS_CV == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); - ZEND_VM_NEXT_OPCODE(); -} + 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_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *expr_ptr, new_expr; + 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)) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); - SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = zend_get_bad_ptr(); - 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_tmp(opline->op1.var EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_TMP_VAR) { - /* pass */ - } else if (IS_TMP_VAR == IS_CONST) { - Z_TRY_ADDREF_P(expr_ptr); - } else if (IS_TMP_VAR == IS_CV) { - ZVAL_DEREF(expr_ptr); - Z_TRY_ADDREF_P(expr_ptr); - } else /* if (IS_TMP_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { - zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); - expr_ptr = Z_REFVAL_P(expr_ptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); + if (EXPECTED(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_known_hash(zobj->properties, name); + 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; + } + } } } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - zend_string *str; - zend_ulong hval; + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); -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_safe(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_array_offset_access(offset); - zval_ptr_dtor_nogc(expr_ptr); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { - zend_cannot_add_element(); - zval_ptr_dtor_nogc(expr_ptr); + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } - } + } while (0); + +fetch_obj_is_finish: + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_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) { - zval *array; - uint32_t size; +#if 0 USE_OPLINE +#endif - 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 (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_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +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, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); + SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); + 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, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } - /* 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; +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (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); + zval *property_val; - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + 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); - 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 (UNEXPECTED(prop_info != NULL)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } } } else { - zval *value_ptr = zend_get_bad_ptr(); - - /* 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; + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); } + zobj->properties = zend_array_dup(zobj->properties); } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } - } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } } } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); } 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)); + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { - 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); + UNDEF_RESULT(); + goto exit_assign_obj; } - } 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; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); } - /* 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_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - 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_CASE_STRICT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - 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 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); -} +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - bool result; +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } - 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); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - bool result; + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(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->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) -{ -#if 0 - USE_OPLINE -#endif + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - if (IS_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_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_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - if (IS_TMP_VAR == IS_UNUSED) { - SAVE_OPLINE(); - zend_verify_missing_return_type(EX(func)); - HANDLE_EXCEPTION(); - } else { -/* prevents "undefined variable opline" errors */ -#if 0 || (IS_TMP_VAR != IS_UNUSED) - USE_OPLINE - zval *retval_ref, *retval_ptr; - zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - retval_ref = retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - - if (IS_TMP_VAR == IS_CONST) { - 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_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); - } - ZVAL_DEREF(retval_ptr); - } else if (IS_TMP_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(); - } +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (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); + zval *property_val; - if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { - SAVE_OPLINE(); - retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { - ZEND_VM_NEXT_OPCODE(); - } - } + 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_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); + if (UNEXPECTED(prop_info != NULL)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } } 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); + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } - retval_ptr = retval_ref; } } - - SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { - zend_verify_return_error(EX(func), retval_ptr); - HANDLE_EXCEPTION(); + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; } - ZEND_VM_NEXT_OPCODE(); -#endif } -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value, *arg; - uint32_t arg_num; + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } - if (IS_UNUSED == IS_CONST) { - SAVE_OPLINE(); - zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); - if (UNEXPECTED(!arg)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - } else { - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - arg_num = opline->op2.num; + 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 (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(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(arg, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); - } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); } - 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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_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, *arg; - uint32_t arg_num; + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; - if (IS_UNUSED == IS_CONST) { - SAVE_OPLINE(); - zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); - if (UNEXPECTED(!arg)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - } else { - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - arg_num = opline->op2.num; - } + SAVE_OPLINE(); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - 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(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } - value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(arg, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); + 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, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } - ZEND_VM_NEXT_OPCODE(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *expr_ptr, new_expr; +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (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); + zval *property_val; - SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = zend_get_bad_ptr(); - 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_tmp(opline->op1.var EXECUTE_DATA_CC); - if (IS_TMP_VAR == IS_TMP_VAR) { - /* pass */ - } else if (IS_TMP_VAR == IS_CONST) { - Z_TRY_ADDREF_P(expr_ptr); - } else if (IS_TMP_VAR == IS_CV) { - ZVAL_DEREF(expr_ptr); - Z_TRY_ADDREF_P(expr_ptr); - } else /* if (IS_TMP_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { - zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + if (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); - 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 (UNEXPECTED(prop_info != NULL)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } } - } - } - } - - if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; - zend_string *str; - zend_ulong hval; -add_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_UNUSED != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { - offset = Z_REFVAL_P(offset); - goto add_again; - } else if (Z_TYPE_P(offset) == IS_NULL) { - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else if (Z_TYPE_P(offset) == IS_DOUBLE) { - hval = zend_dval_to_lval_safe(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_array_offset_access(offset); - zval_ptr_dtor_nogc(expr_ptr); } - + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var 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); + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; } } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zval *array; - uint32_t size; - USE_OPLINE + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } - array = EX_VAR(opline->result.var); - if (IS_TMP_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - ZVAL_ARR(array, zend_new_array(size)); - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init_mixed(Z_ARRVAL_P(array)); - } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); + 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)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; 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); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); + 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, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } - /* 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; +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (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); + zval *property_val; - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + 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); - 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 (UNEXPECTED(prop_info != NULL)) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } } } else { - zval *value_ptr = zend_get_bad_ptr(); - - /* 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; + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); } + zobj->properties = zend_array_dup(zobj->properties); } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } - } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + 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, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; } } } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); } 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); + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { - 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); + UNDEF_RESULT(); + goto exit_assign_obj; } - } 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; + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); } - /* 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(); + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); - ZEND_VM_RETURN(); -} + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } -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; +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } - SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - type = zend_zval_get_legacy_type(op1); - if (EXPECTED(type)) { - ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); - } else { - ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; - bool result; + zval *property, *container, *value_ptr; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - ZEND_VM_SMART_BRANCH(result, 1); -} + 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); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + if (1) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } } - 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_assign_to_property_reference(container, (IS_TMP_VAR|IS_VAR), property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); } -} -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 + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - 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_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + 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_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; - zval *var; + zval *property, *container, *value_ptr; - /* op1 and result are the same */ - rope = (zend_string**)EX_VAR(opline->op1.var); - if (IS_CV == IS_CONST) { - var = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - rope[opline->extended_value] = Z_STR_P(var); - if (UNEXPECTED(Z_REFCOUNTED_P(var))) { - Z_ADDREF_P(var); - } - } else { - var = EX_VAR(opline->op2.var); - if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { - if (IS_CV == IS_CV) { - rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + SAVE_OPLINE(); + + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); } else { - rope[opline->extended_value] = Z_STR_P(var); + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); } } else { - SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + 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); } - rope[opline->extended_value] = zval_get_string_func(var); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } + } else { + 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(); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; - zval *var, *ret; - uint32_t i; + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; - 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)); + + 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; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_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 { - rope[opline->extended_value] = Z_STR_P(var); + ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - } else { - SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); } - rope[opline->extended_value] = zval_get_string_func(var); + } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } 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); - 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(); + 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); + GC_ADD_FLAGS(str, flags); + 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); + GC_ADD_FLAGS(str, flags); + 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(); } - size_t len = 0; - uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES; - for (i = 0; i <= opline->extended_value; i++) { - flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]); - len += ZSTR_LEN(rope[i]); - } - ret = EX_VAR(opline->result.var); - ZVAL_STR(ret, zend_string_alloc(len, 0)); - GC_ADD_FLAGS(Z_STR_P(ret), flags); - - char *target = Z_STRVAL_P(ret); - for (i = 0; i <= opline->extended_value; i++) { - memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); - target += ZSTR_LEN(rope[i]); - zend_string_release_ex(rope[i], 0); - } - *target = '\0'; - - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *expr_ptr, new_expr; - SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = zend_get_bad_ptr(); - if (Z_ISREF_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } else { - ZVAL_MAKE_REF_EX(expr_ptr, 2); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + 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 { - 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_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); + } + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; } } - } - - if (IS_CV != IS_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; + 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_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_safe(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_array_offset_access(offset); - zval_ptr_dtor_nogc(expr_ptr); } + 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); - } 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); + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + 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(); } -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_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *array; - uint32_t size; 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; - array = EX_VAR(opline->result.var); - if (IS_TMP_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - ZVAL_ARR(array, zend_new_array(size)); - /* Explicitly initialize array as not-packed if flag is set */ - if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { - zend_hash_real_init_mixed(Z_ARRVAL_P(array)); - } - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZVAL_ARR(array, zend_new_array(0)); - ZEND_VM_NEXT_OPCODE(); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + SAVE_OPLINE(); - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + object = _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 (IS_CV != IS_CONST) { + function_name = EX_VAR(opline->op2.var); } - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); + 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"); - /* 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)); + HANDLE_EXCEPTION(); + } while (0); + } - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); - 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); + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; } } - } else { - zval *value_ptr = zend_get_bad_ptr(); + 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) { - /* 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; } + HANDLE_EXCEPTION(); } - 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_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(); } - } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + } while (0); + } - /* 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)); + called_scope = obj->ce; - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } + if (IS_CV == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } + zend_object *orig_obj = obj; - /* 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); + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); } - 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); - } + /* 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 (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 (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + 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)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } } - /* 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(); -} + if (IS_CV != IS_CONST) { -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *closure, *var; + } - 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 { - ZVAL_MAKE_REF_EX(var, 2); - } - } 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(); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } } - ZVAL_DEREF(var); - Z_TRY_ADDREF_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 */ + } + /* 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_closure_bind_var_ex(closure, - (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)), var); + 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_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_CASE_SPEC_TMPVAR_CV_HANDLER(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_UNDEFINED_OP1(); - ZVAL_NULL(var_ptr); - } + zval *op1, *op2; + double d1, d2; - 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; + 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; } - 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)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; - - 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(0)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } 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; } - 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); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - 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 (result) { + goto case_true; + } else { + goto case_false; + } } - ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -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_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zval *container; + bool result; + zend_ulong hval; + zval *offset; SAVE_OPLINE(); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - ZVAL_NULL(var_ptr); - } + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = EX_VAR(opline->op2.var); - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); - break; +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(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; } } - 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; + 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); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { + /* avoid exception check */ - 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_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; } - ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; - - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - fast_long_decrement_function(var_ptr); - if (UNEXPECTED(1)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); - } - ZEND_VM_NEXT_OPCODE(); + if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); } - ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +isset_dim_obj_exit: + + 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_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - ZVAL_NULL(var_ptr); - } - - 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); + 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 (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); - break; + 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; } - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); - - increment_function(var_ptr); - } while (0); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *var_ptr; + 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; + } + } - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + 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)); - if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { - ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); - fast_long_increment_function(var_ptr); - ZEND_VM_NEXT_OPCODE(); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } - ZEND_VM_TAIL_CALL(zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +isset_object_finish: + + 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_post_dec_helper_SPEC_VAR(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 *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zval *key, *subject; + HashTable *ht; + bool result; SAVE_OPLINE(); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - ZVAL_NULL(var_ptr); - } - 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); + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + subject = EX_VAR(opline->op2.var); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); - break; + if (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; } } - 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_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - ZEND_VM_TAIL_CALL(zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + 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_RETURN_SPEC_VAR_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) { USE_OPLINE zval *retval_ptr; zval *return_value; - retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_tmp(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)) { + 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_VAR & (IS_VAR|IS_TMP_VAR)) { + 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_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); - if (IS_VAR == IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { Z_ADDREF_P(return_value); } } - } else if (IS_VAR == IS_CV) { + } else if (IS_TMP_VAR == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { @@ -22032,7 +21970,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA } ZVAL_COPY_VALUE(return_value, retval_ptr); } while (0); - } else /* if (IS_VAR == IS_VAR) */ { + } else /* if (IS_TMP_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); @@ -22054,7 +21992,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_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; @@ -22065,31 +22003,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER return_value = EX(return_value); do { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR)) || - (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { + 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_var(opline->op1.var EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (!return_value) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(return_value, retval_ptr); break; } ZVAL_NEW_REF(return_value, retval_ptr); - if (IS_VAR == IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } } break; } - retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + retval_ptr = zend_get_bad_ptr(); - if (IS_VAR == IS_VAR) { + 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"); @@ -22118,7 +22056,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval; @@ -22126,19 +22064,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HAND zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); - retval = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + retval = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(&generator->retval, retval); - if (IS_VAR == IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { Z_ADDREF(generator->retval); } } - } else if (IS_VAR == IS_CV) { + } else if (IS_TMP_VAR == IS_CV) { ZVAL_COPY_DEREF(&generator->retval, retval); - } else /* if (IS_VAR == IS_VAR) */ { + } else /* if (IS_TMP_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval))) { zend_refcounted *ref = Z_COUNTED_P(retval); @@ -22163,14 +22101,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HAND ZEND_VM_RETURN(); } -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_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *arg, *param; SAVE_OPLINE(); - arg = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + arg = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); param = ZEND_CALL_VAR(EX(call), opline->result.var); 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); @@ -22184,7 +22122,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -22192,7 +22130,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC HashTable *ht; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); switch (opline->extended_value) { case IS_LONG: @@ -22206,28 +22144,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC break; default: ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); - if (IS_VAR & (IS_VAR|IS_CV)) { + 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_VAR == IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_VAR != IS_TMP_VAR) { + } else if (IS_TMP_VAR != IS_TMP_VAR) { if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } if (opline->extended_value == IS_ARRAY) { - if (IS_VAR == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { + 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_VAR == IS_CONST) { + 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); @@ -22266,7 +22203,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC } else if (Z_TYPE_P(expr) != IS_NULL) { Z_OBJ_P(result)->properties = ht = zend_new_array(1); expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); - if (IS_VAR == IS_CONST) { + 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); @@ -22279,25 +22216,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC 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_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *result; SAVE_OPLINE(); - array_ptr = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + 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_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + if (IS_TMP_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)) { + } 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 = zobj->properties; @@ -22314,18 +22250,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); - if (IS_VAR != IS_TMP_VAR) { + if (IS_TMP_VAR != IS_TMP_VAR) { Z_ADDREF_P(array_ptr); } if (zend_hash_num_elements(properties) == 0) { Z_FE_ITER_P(result) = (uint32_t) -1; - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); @@ -22348,24 +22284,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE } } -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_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *array_ref; SAVE_OPLINE(); - 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 (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + array_ref = array_ptr = zend_get_bad_ptr(); 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); + 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_VAR == IS_VAR || IS_VAR == IS_CV) { + 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); @@ -22377,19 +22313,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z ZVAL_NEW_REF(array_ref, array_ptr); array_ptr = Z_REFVAL_P(array_ref); } - if (IS_VAR == IS_CONST) { + 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); - 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)) { + } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { if (!Z_OBJCE_P(array_ptr)->get_iterator) { HashTable *properties; - if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + 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); @@ -22411,12 +22346,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z properties = Z_OBJPROP_P(array_ptr); if (zend_hash_num_elements(properties) == 0) { 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)); } 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 { bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); @@ -22438,300 +22373,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array; - zval *value; - uint32_t value_type; - HashTable *fe_ht; - HashPosition pos; - - array = EX_VAR(opline->op1.var); - if (UNEXPECTED(Z_TYPE_P(array) != IS_ARRAY)) { - ZEND_VM_TAIL_CALL(zend_fe_fetch_object_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - fe_ht = Z_ARRVAL_P(array); - pos = Z_FE_POS_P(array); - if (HT_IS_PACKED(fe_ht)) { - value = fe_ht->arPacked + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); - } - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; - } - pos++; - value++; - } - Z_FE_POS_P(array) = pos + 1; - if (RETURN_VALUE_USED(opline)) { - ZVAL_LONG(EX_VAR(opline->result.var), pos); - } - } else { - Bucket *p; - - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); - } - pos++; - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; - } - p++; - } - Z_FE_POS_P(array) = pos; - 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); - } - } - } - if (EXPECTED(opline->op2_type == IS_CV)) { - zval *variable_ptr = EX_VAR(opline->op2.var); - SAVE_OPLINE(); - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } 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(); + 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_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array; zval *value; - uint32_t value_type; - HashTable *fe_ht; - HashPosition pos; - Bucket *p; + zend_reference *ref = NULL; + bool ret; - array = EX_VAR(opline->op1.var); SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - ZVAL_DEREF(array); - if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { - pos = zend_hash_iterator_pos_ex(Z_FE_ITER_P(EX_VAR(opline->op1.var)), array); - fe_ht = Z_ARRVAL_P(array); - if (HT_IS_PACKED(fe_ht)) { - value = fe_ht->arPacked + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - goto fe_fetch_w_exit; - } - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; - } - pos++; - value++; - } - EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; - if (RETURN_VALUE_USED(opline)) { - ZVAL_LONG(EX_VAR(opline->result.var), pos); - } - } else { - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - goto fe_fetch_w_exit; - } - pos++; - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; - } - p++; - } - EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; - 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 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; - } - pos++; - 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_property_info_for_slot(Z_OBJ_P(array), value); - if (UNEXPECTED(prop_info)) { - if (UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { - zend_throw_error(NULL, - "Cannot acquire reference to readonly property %s::$%s", - ZSTR_VAL(prop_info->ce->name), ZSTR_VAL(p->key)); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - if (ZEND_TYPE_IS_SET(prop_info->type)) { - 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; - } - } - p++; - } - EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; - 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); - } - } - } else { - const zend_object_iterator_funcs *funcs = iter->funcs; - 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. */ - funcs->move_forward(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - if (UNEXPECTED(funcs->valid(iter) == FAILURE)) { - /* reached end of iteration */ - if (UNEXPECTED(EG(exception) != NULL)) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - goto fe_fetch_w_exit; - } - } - value = 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 (funcs->get_current_key) { - 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_zval_value_name(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; - zend_reference *ref = NULL; - bool 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) { + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { ref = Z_REF_P(value); } value = Z_REFVAL_P(value); @@ -22749,11 +22413,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_ zval *result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, value); - if (IS_VAR == IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_VAR == IS_CV) { + } else if (IS_TMP_VAR == IS_CV) { if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if (IS_VAR == IS_VAR && ref) { + } else if (IS_TMP_VAR == IS_VAR && ref) { if (UNEXPECTED(GC_DELREF(ref) == 0)) { efree_size(ref, sizeof(zend_reference)); } else if (Z_OPT_REFCOUNTED_P(result)) { @@ -22767,17 +22431,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; zend_reference *ref = NULL; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - if (IS_VAR & IS_VAR) { + if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (IS_TMP_VAR & IS_VAR) { ref = Z_REF_P(value); } value = Z_REFVAL_P(value); @@ -22786,11 +22450,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND 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 (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_VAR == IS_CV) { + } else if (IS_TMP_VAR == IS_CV) { if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if ((IS_VAR & IS_VAR) && ref) { + } else if ((IS_TMP_VAR & IS_VAR) && ref) { if (UNEXPECTED(GC_DELREF(ref) == 0)) { efree_size(ref, sizeof(zend_reference)); } else if (Z_OPT_REFCOUNTED_P(result)) { @@ -22800,7 +22464,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } - if ((IS_VAR & IS_VAR) && ref) { + if ((IS_TMP_VAR & IS_VAR) && ref) { if (UNEXPECTED(GC_DELREF(ref) == 0)) { efree_size(ref, sizeof(zend_reference)); } @@ -22808,16 +22472,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val, *result; - val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + val = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_P(val) > IS_NULL) { do { - if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) { + if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) { val = Z_REFVAL_P(val); if (Z_TYPE_P(val) <= IS_NULL) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -22832,7 +22496,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_VAR_ uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK; if (EXPECTED(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) { ZVAL_NULL(result); - if (IS_VAR == IS_CV + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF) && (opline->extended_value & ZEND_JMP_NULL_BP_VAR_IS) == 0 ) { @@ -22852,23 +22516,23 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_VAR_ ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *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)) { + 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_VAR == IS_CV) { + if (IS_TMP_VAR == IS_CV) { ZVAL_COPY_DEREF(result, value); - } else if (IS_VAR == IS_VAR) { + } 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)) { @@ -22881,7 +22545,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR } } else { ZVAL_COPY_VALUE(result, value); - if (IS_VAR == IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { Z_ADDREF_P(result); } @@ -22890,31 +22554,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR 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_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_identical_function(op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -22922,28 +22569,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_identical_function(op1, op2); 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + 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)); @@ -22951,1060 +22598,3213 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONS 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { +#if 0 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); +#endif - 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 (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)); } - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); + 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)); } - } 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); + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } } -/* 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - zval *value, *container, *dim; - HashTable *ht; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_string **rope; + zval *var; - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { -assign_dim_op_array: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); -assign_dim_op_new_array: - dim = RT_CONSTANT(opline, opline->op2); - if (IS_CONST == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(ht, &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(ht, dim EXECUTE_DATA_CC); + /* 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 { - var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); } - if (UNEXPECTED(!var_ptr)) { - goto assign_dim_op_ret_null; + } 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); - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} - 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); +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; - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + 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); } - 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; + 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 (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - zend_object *obj = Z_OBJ_P(container); - - dim = RT_CONSTANT(opline, opline->op2); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; + } else { + SAVE_OPLINE(); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); } - zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); - } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { - uint8_t old_type; + rope[opline->extended_value] = zval_get_string_func(var); - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - ht = zend_new_array(8); - old_type = Z_TYPE_P(container); - ZVAL_ARR(container, ht); - if (UNEXPECTED(old_type == IS_FALSE)) { - GC_ADDREF(ht); - zend_false_to_array_deprecated(); - if (UNEXPECTED(GC_DELREF(ht) == 0)) { - zend_array_destroy(ht); - goto assign_dim_op_ret_null; + if (UNEXPECTED(EG(exception))) { + for (i = 0; i <= opline->extended_value; i++) { + zend_string_release_ex(rope[i], 0); } - } - goto assign_dim_op_new_array; - } else { - dim = RT_CONSTANT(opline, opline->op2); - zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); -assign_dim_op_ret_null: - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_EX(1, 2); + size_t len = 0; + uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES; + for (i = 0; i <= opline->extended_value; i++) { + flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]); + len += ZSTR_LEN(rope[i]); + } + ret = EX_VAR(opline->result.var); + ZVAL_STR(ret, zend_string_alloc(len, 0)); + GC_ADD_FLAGS(Z_STR_P(ret), flags); + + char *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_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_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); + zval *value, *arg; + uint32_t arg_num; - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } - 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); + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + 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(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + 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_PRE_INC_OBJ_SPEC_VAR_CONST_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 *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - 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 = 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); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - UNDEF_RESULT(); - break; - } + ZVAL_MAKE_REF_EX(expr_ptr, 2); } - 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); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.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); } - 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; - } + if (IS_CONST != IS_UNUSED) { + zval *offset = RT_CONSTANT(opline, opline->op2); + zend_string *str; + zend_ulong hval; -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); +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; } - - zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_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_safe(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_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); - } - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); } - } while (0); - 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_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zval *array; + uint32_t size; USE_OPLINE - zval *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); + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - 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); + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + 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)); } - 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 + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + /* 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 = zend_get_bad_ptr(); + + /* 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); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } 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_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)); + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; + /* 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); - 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 (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_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; } - 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; + /* 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(); - 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 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(); + ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *result; + zval *op1; + HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + zval *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 OPLINE_CC EXECUTE_DATA_CC); + 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); + if (IS_TMP_VAR & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + ZEND_VM_SMART_BRANCH(result, 0); + } - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + if (opline->extended_value) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); + } + SAVE_OPLINE(); + if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } else if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + } else if (Z_TYPE_P(op1) <= IS_FALSE) { + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + result = zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC()); + ZEND_VM_SMART_BRANCH(result, 0); + } else { + zend_string *key; + zval key_tmp; + + if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } + + SAVE_OPLINE(); + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { + ZVAL_STR(&key_tmp, key); + if (zend_compare(op1, &key_tmp) == 0) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(1, 1); + } + } ZEND_HASH_FOREACH_END(); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(0, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(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 #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))) { + 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_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(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)); - } -} - -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 OPLINE_CC EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CONST_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 *container, *dim; + zend_string **rope; + zval *var; - 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); + /* 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 { - zend_fetch_dimension_address_W(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + 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_CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_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 *object, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; - - SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_string **rope; + zval *var, *ret; + uint32_t i; - 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; + rope = (zend_string**)EX_VAR(opline->op1.var); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (UNEXPECTED(EG(exception))) { + for (i = 0; i <= opline->extended_value; i++) { + zend_string_release_ex(rope[i], 0); + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } } - zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) 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) { - if (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); - zval *property_val; + size_t len = 0; + uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES; + for (i = 0; i <= opline->extended_value; i++) { + flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]); + len += ZSTR_LEN(rope[i]); + } + ret = EX_VAR(opline->result.var); + ZVAL_STR(ret, zend_string_alloc(len, 0)); + GC_ADD_FLAGS(Z_STR_P(ret), flags); - 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); + char *target = Z_STRVAL_P(ret); + for (i = 0; i <= opline->extended_value; i++) { + memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); + target += ZSTR_LEN(rope[i]); + zend_string_release_ex(rope[i], 0); + } + *target = '\0'; - if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } - } else { - name = Z_STR_P(RT_CONSTANT(opline, opline->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_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; - } - } + ZEND_VM_NEXT_OPCODE(); +} - if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); } - name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); - if (UNEXPECTED(!name)) { + 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); - UNDEF_RESULT(); - goto exit_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 (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - ZVAL_DEREF(value); - } - - value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : 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; - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); +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_safe(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_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } +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 -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); + 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(); } - - 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; - SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.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, RT_CONSTANT(opline, opline->op2) 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_CONST == IS_CONST) { - if (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); - 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)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + /* 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 { - name = Z_STR_P(RT_CONSTANT(opline, opline->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); + zval *value_ptr = zend_get_bad_ptr(); + + /* 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; } - zobj->properties = zend_array_dup(zobj->properties); } - property_val = zend_hash_find_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; + 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); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } 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 (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); } } } - name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); } else { - name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; - } - } - - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(value); + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); } - value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + /* Set the new yielded key */ + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if (IS_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); } -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); + 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_obj 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(); } -/* 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) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; + zval *op1, *op2; + bool result; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - 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, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + 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_CASE_STRICT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->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) +{ + USE_OPLINE + zval *op1, *op2; + 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); + 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_CASE_STRICT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(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->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) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_UNUSED == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } +} -assign_object: - zobj = Z_OBJ_P(object); - if (IS_CONST == IS_CONST) { - if (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); - zval *property_val; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (IS_TMP_VAR == IS_UNUSED) { + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); + } else { +/* prevents "undefined variable opline" errors */ +#if 0 || (IS_TMP_VAR != IS_UNUSED) + USE_OPLINE + zval *retval_ref, *retval_ptr; + zend_arg_info *ret_info = EX(func)->common.arg_info - 1; + retval_ref = retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { - property_val = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + if (IS_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_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); + } + ZVAL_DEREF(retval_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(retval_ptr); + } - if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + 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, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +#endif + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + 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(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + 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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + 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(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + 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_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + 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_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_UNUSED != IS_UNUSED) { + zval *offset = NULL; + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_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_safe(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_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); } } } else { - name = Z_STR_P(RT_CONSTANT(opline, opline->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); + zval *value_ptr = zend_get_bad_ptr(); + + /* 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; } - zobj->properties = zend_array_dup(zobj->properties); } - property_val = zend_hash_find_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; + 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); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } 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_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_legacy_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_CASE_STRICT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + 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)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var; + + /* op1 and result are the same */ + rope = (zend_string**)EX_VAR(opline->op1.var); + if (IS_CV == IS_CONST) { + var = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CV == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +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; + + rope = (zend_string**)EX_VAR(opline->op1.var); + if (IS_CV == IS_CONST) { + var = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CV == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + + if (UNEXPECTED(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(); + } + } + } + + size_t len = 0; + uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES; + for (i = 0; i <= opline->extended_value; i++) { + flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]); + len += ZSTR_LEN(rope[i]); + } + ret = EX_VAR(opline->result.var); + ZVAL_STR(ret, zend_string_alloc(len, 0)); + GC_ADD_FLAGS(Z_STR_P(ret), flags); + + char *target = Z_STRVAL_P(ret); + for (i = 0; i <= opline->extended_value; i++) { + memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); + target += ZSTR_LEN(rope[i]); + zend_string_release_ex(rope[i], 0); + } + *target = '\0'; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + 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_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_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_safe(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_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_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) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = zend_get_bad_ptr(); + + /* 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); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } 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_CV != IS_UNUSED) { + zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + 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_BIND_LEXICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *closure, *var; + + 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 { + ZVAL_MAKE_REF_EX(var, 2); + } + } 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(); + } + } + ZVAL_DEREF(var); + Z_TRY_ADDREF_P(var); + } + + zend_closure_bind_var_ex(closure, + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)), var); + ZEND_VM_NEXT_OPCODE(); +} + +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_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + 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; + } + } + 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)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + 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(0)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + 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); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +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; + + 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_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + 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; + } + } + decrement_function(var_ptr); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(0)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_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_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + + increment_function(var_ptr); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + fast_long_increment_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +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; + + 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_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + 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_CALL_OBSERVED)))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); + 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); + } + } + } + + + + 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) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + SAVE_OPLINE(); + + return_value = EX(return_value); + + 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 (!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(return_value, retval_ptr); + break; + } + + ZVAL_NEW_REF(return_value, retval_ptr); + if (IS_VAR == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } + } + break; + } + + retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR) { + ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); + } else { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + break; + } + } + + if (return_value) { + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } while (0); + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval; + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + retval = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* Copy return value into generator->retval */ + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(&generator->retval, retval); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { + Z_ADDREF(generator->retval); + } + } + } else if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(&generator->retval, retval); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_refcounted *ref = Z_COUNTED_P(retval); + + retval = Z_REFVAL_P(retval); + ZVAL_COPY_VALUE(&generator->retval, retval); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval)) { + Z_ADDREF_P(retval); + } + } else { + ZVAL_COPY_VALUE(&generator->retval, retval); + } + } + + EG(current_execute_data) = EX(prev_execute_data); + + /* 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_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *arg, *param; + + SAVE_OPLINE(); + + arg = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + param = ZEND_CALL_VAR(EX(call), opline->result.var); + 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); + Z_TRY_ADDREF_P(arg); + ZVAL_NEW_REF(param, arg); + } else { + 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); + } + + 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 if (Z_OBJ_P(expr)->properties == NULL + && Z_OBJ_HT_P(expr)->get_properties_for == NULL + && Z_OBJ_HT_P(expr)->get_properties == zend_std_get_properties) { + /* Optimized version without rebuilding properties HashTable */ + ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr))); + } 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); + } + } + } + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array_ptr, *result; + + SAVE_OPLINE(); + + array_ptr = _get_zval_ptr_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 = 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); + } + + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_VAR != IS_TMP_VAR) { + Z_ADDREF_P(array_ptr); + } + + if (zend_hash_num_elements(properties) == 0) { + Z_FE_ITER_P(result) = (uint32_t) -1; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(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_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array_ptr, *array_ref; + + SAVE_OPLINE(); + + 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); + } + + 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); + + 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) { + HashTable *properties; + 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); + } + + properties = Z_OBJPROP_P(array_ptr); + if (zend_hash_num_elements(properties) == 0) { + 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)); + } + + 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 { + bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(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_VM_HOT 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; + + array = EX_VAR(opline->op1.var); + if (UNEXPECTED(Z_TYPE_P(array) != IS_ARRAY)) { + ZEND_VM_TAIL_CALL(zend_fe_fetch_object_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + fe_ht = Z_ARRVAL_P(array); + pos = Z_FE_POS_P(array); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; + } + Z_FE_POS_P(array) = pos + 1; + if (RETURN_VALUE_USED(opline)) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); + } + } else { + Bucket *p; + + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + Z_FE_POS_P(array) = pos; + 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); + } + } + } + if (EXPECTED(opline->op2_type == IS_CV)) { + zval *variable_ptr = EX_VAR(opline->op2.var); + SAVE_OPLINE(); + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } 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(); + } +} + +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(); + + 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); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_w_exit; + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; + } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; + if (RETURN_VALUE_USED(opline)) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); + } + } else { + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_w_exit; + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; + 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 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; + } + pos++; + 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_property_info_for_slot(Z_OBJ_P(array), value); + if (UNEXPECTED(prop_info)) { + if (UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { + zend_throw_error(NULL, + "Cannot acquire reference to readonly property %s::$%s", + ZSTR_VAL(prop_info->ce->name), ZSTR_VAL(p->key)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_IS_SET(prop_info->type)) { + 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; + } + } + p++; + } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; + 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); + } + } + } else { + const zend_object_iterator_funcs *funcs = iter->funcs; + 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. */ + funcs->move_forward(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(funcs->valid(iter) == FAILURE)) { + /* reached end of iteration */ + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + goto fe_fetch_w_exit; + } + } + value = 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 (funcs->get_current_key) { + 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_zval_value_name(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; + zend_reference *ref = NULL; + bool 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 = Z_REF_P(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) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, 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; + zend_reference *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 = Z_REF_P(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) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, 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 ((IS_VAR & IS_VAR) && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val, *result; + + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (Z_TYPE_P(val) > IS_NULL) { + do { + if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + if (Z_TYPE_P(val) <= IS_NULL) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + break; + } + } + ZEND_VM_NEXT_OPCODE(); + } while (0); + } + + result = EX_VAR(opline->result.var); + uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK; + if (EXPECTED(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) { + ZVAL_NULL(result); + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF) + && (opline->extended_value & ZEND_JMP_NULL_BP_VAR_IS) == 0 + ) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + } else if (short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) { + ZVAL_FALSE(result); + } else { + ZEND_ASSERT(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY); + ZVAL_TRUE(result); + } + + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); +} + +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_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + 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_CASE_STRICT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + 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); + + 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; + 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_DIM_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; + HashTable *ht; + + 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); + ht = Z_ARRVAL_P(container); +assign_dim_op_new_array: + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(ht, &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(ht, dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(ht, 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; + } + } + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + uint8_t old_type; + + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } + } + goto assign_dim_op_new_array; + } else { + dim = RT_CONSTANT(opline, opline->op2); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + 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_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_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); } - if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); } - name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - } else { - name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } - } + } while (0); - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(value); - } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; - if (IS_CONST != 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_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* 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_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; + zval *container; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.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_RW(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, RT_CONSTANT(opline, opline->op2) 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_CONST == IS_CONST) { - if (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); - 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)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } - } else { - name = Z_STR_P(RT_CONSTANT(opline, opline->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_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; - } - } +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 (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - 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)); } - name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); - if (UNEXPECTED(!name)) { - - UNDEF_RESULT(); - goto exit_assign_obj; + if (IS_CONST == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } +} - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(value); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; - value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + 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_CONST != IS_CONST) { - zend_tmp_string_release(tmp_name); + 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)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), 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; + + 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 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: - if (garbage) { - GC_DTOR_NO_REF(garbage); +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); } - 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_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -24673,80 +26473,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *property, *container, *value_ptr; - - SAVE_OPLINE(); - - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = RT_CONSTANT(opline, opline->op2); - - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - - if (1) { - if (IS_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_VAR, property, IS_CONST, 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_CONST_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 = 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_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_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); -} - -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -24819,252 +26545,76 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } 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))) && - EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - 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) { - - } - } 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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - - if (IS_CONST == IS_CONST) { - SAVE_OPLINE(); - zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - uint32_t arg_num; - arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); - if (UNEXPECTED(!arg)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - } else { - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - } - - 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(); - ZVAL_NULL(arg); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - - if (IS_VAR == IS_CV) { - ZVAL_COPY_DEREF(arg, varptr); - } else /* if (IS_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(varptr))) { - zend_refcounted *ref = Z_COUNTED_P(varptr); - - varptr = Z_REFVAL_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); - } - } else { - ZVAL_COPY_VALUE(arg, varptr); - } - } - - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - - if (IS_CONST == IS_CONST) { - SAVE_OPLINE(); - zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - uint32_t arg_num; - arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); - if (UNEXPECTED(!arg)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - } else { - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - } - - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(arg, varptr); - - if (EXPECTED(Z_ISREF_P(varptr))) { - ZEND_VM_NEXT_OPCODE(); - } - - SAVE_OPLINE(); - ZVAL_NEW_REF(arg, arg); - zend_error(E_NOTICE, "Only variables should be passed by reference"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - uint32_t arg_num; - - if (IS_CONST == IS_CONST) { - SAVE_OPLINE(); - zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); - if (UNEXPECTED(!arg)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - HANDLE_EXCEPTION(); - } - } else { - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - arg_num = opline->op2.num; - } - - if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { - if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_var; - } - - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(arg, varptr); - - if (EXPECTED(Z_ISREF_P(varptr) || - QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); - } - } else { - if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_var; - } - - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(arg, varptr); - - if (EXPECTED(Z_ISREF_P(varptr) || - ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); - } - } - - SAVE_OPLINE(); - ZVAL_NEW_REF(arg, arg); - zend_error(E_NOTICE, "Only variables should be passed by reference"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zend_undefined_method(ce, Z_STR_P(function_name)); + } -send_var: - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(Z_ISREF_P(varptr))) { - zend_refcounted *ref = Z_COUNTED_P(varptr); + HANDLE_EXCEPTION(); + } + if (IS_CONST == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + 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) { - 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(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_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - SAVE_OPLINE(); - if (IS_CONST == IS_CONST) { - zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - uint32_t arg_num; - arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); - if (UNEXPECTED(!arg)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + 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 { - arg = ZEND_CALL_VAR(EX(call), opline->result.var); + /* 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; } - varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (Z_ISREF_P(varptr)) { - Z_ADDREF_P(varptr); - } else { - ZVAL_MAKE_REF_EX(varptr, 2); - } - ZVAL_REF(arg, Z_REF_P(varptr)); + 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)); ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; - uint32_t arg_num; if (IS_CONST == IS_CONST) { SAVE_OPLINE(); zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -25072,25 +26622,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HAN } } else { arg = ZEND_CALL_VAR(EX(call), opline->result.var); - arg_num = opline->op2.num; - } - - if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { - 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: - varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (Z_ISREF_P(varptr)) { - Z_ADDREF_P(varptr); - } else { - ZVAL_MAKE_REF_EX(varptr, 2); - } - ZVAL_REF(arg, Z_REF_P(varptr)); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE(); } varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -25122,13 +26653,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HAN ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; if (IS_CONST == IS_CONST) { - // TODO: Would it make sense to share the cache slot with CHECK_FUNC_ARG? SAVE_OPLINE(); zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); uint32_t arg_num; @@ -25141,612 +26671,235 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC arg = ZEND_CALL_VAR(EX(call), opline->result.var); } - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (Z_ISREF_P(varptr)) { - Z_ADDREF_P(varptr); - } else { - ZVAL_MAKE_REF_EX(varptr, 2); - } - ZVAL_REF(arg, Z_REF_P(varptr)); - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE(); - } - varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); - if (UNEXPECTED(Z_ISREF_P(varptr))) { - zend_refcounted *ref = Z_COUNTED_P(varptr); - - varptr = Z_REFVAL_P(varptr); - ZVAL_COPY_VALUE(arg, varptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); - } - } else { - ZVAL_COPY_VALUE(arg, varptr); - } - - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zend_class_entry *ce, *scope; - zend_class_constant *c; - zval *value, *zv, *constant_zv; - zend_string *constant_name; - USE_OPLINE - - SAVE_OPLINE(); - - do { - if (IS_VAR == IS_CONST && IS_CONST == IS_CONST) { - if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { - value = CACHED_PTR(opline->extended_value + sizeof(void*)); - break; - } - } - if (IS_VAR == IS_CONST) { - 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)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - - HANDLE_EXCEPTION(); - } - CACHE_PTR(opline->extended_value, ce); - } - } else if (IS_VAR == IS_UNUSED) { - ce = zend_fetch_class(NULL, opline->op1.num); - if (UNEXPECTED(ce == NULL)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - - HANDLE_EXCEPTION(); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - } - if (IS_VAR != IS_CONST - && IS_CONST == IS_CONST - && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { - value = CACHED_PTR(opline->extended_value + sizeof(void*)); - break; - } - - constant_zv = RT_CONSTANT(opline, opline->op2); - if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) { - zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - - HANDLE_EXCEPTION(); - } - constant_name = Z_STR_P(constant_zv); - /* Magic 'class' for constant OP2 is caught at compile-time */ - if (IS_CONST != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); - - ZEND_VM_NEXT_OPCODE(); - } - zv = IS_CONST == IS_CONST - ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name) - : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name); - - 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 constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - - HANDLE_EXCEPTION(); - } - - if (ce->ce_flags & ZEND_ACC_TRAIT) { - zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - - HANDLE_EXCEPTION(); - } - - bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated)) { - zend_error(E_DEPRECATED, "Constant %s::%s is deprecated", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); - - if (EG(exception)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - - HANDLE_EXCEPTION(); - } - } - - value = &c->value; - // Enums require loading of all class constants to build the backed enum table - if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { - if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - - HANDLE_EXCEPTION(); - } - } - if (Z_TYPE_P(value) == IS_CONSTANT_AST) { - if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - - HANDLE_EXCEPTION(); - } - } - if (IS_CONST == IS_CONST && !is_constant_deprecated) { - CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); - } - } else { - zend_throw_error(NULL, "Undefined constant %s::%s", - ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); - 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; - - 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); - - expr_ptr = Z_REFVAL_P(expr_ptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { - Z_ADDREF_P(expr_ptr); - } - } - } - } - - if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); - zend_string *str; - zend_ulong hval; - -add_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } - } -str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { - offset = Z_REFVAL_P(offset); - goto add_again; - } else if (Z_TYPE_P(offset) == IS_NULL) { - str = ZSTR_EMPTY_ALLOC(); - goto str_index; - } else if (Z_TYPE_P(offset) == IS_DOUBLE) { - hval = zend_dval_to_lval_safe(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_array_offset_access(offset); - zval_ptr_dtor_nogc(expr_ptr); - } - - } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { - zend_cannot_add_element(); - zval_ptr_dtor_nogc(expr_ptr); - } - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zval *array; - uint32_t size; - USE_OPLINE - - array = EX_VAR(opline->result.var); - if (IS_VAR != IS_UNUSED) { - size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - 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)); + if (EXPECTED(Z_ISREF_P(varptr))) { ZEND_VM_NEXT_OPCODE(); } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - zval *offset; - zend_ulong hval; - zend_string *key; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - offset = RT_CONSTANT(opline, opline->op2); - - 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_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(key, hval)) { - goto num_index_dim; - } - } -str_index_dim: - ZEND_ASSERT(ht != &EG(symbol_table)); - 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_safe(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) { - zend_use_resource_as_offset(offset); - 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_illegal_array_offset_unset(offset); - } - break; - } else if (Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto unset_dim_array; - } - } - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - container = ZVAL_UNDEFINED_OP1(); - } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { - offset = ZVAL_UNDEFINED_OP2(); - } - if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { - offset++; - } - Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_throw_error(NULL, "Cannot unset string offsets"); - } else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) { - zend_throw_error(NULL, "Cannot unset offset in a non-array variable"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) { - zend_false_to_array_deprecated(); - } - } 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_UNSET_OBJ_SPEC_VAR_CONST_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 = RT_CONSTANT(opline, opline->op2); - - do { - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { - if (Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (Z_TYPE_P(container) != IS_OBJECT) { - if (IS_VAR == IS_CV - && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - break; - } - } else { - break; - } - } - if (IS_CONST == IS_CONST) { - name = Z_STR_P(offset); - } else { - 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_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->op1.var)); + 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_VAR_NO_REF_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; } - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); - /* 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(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)) { + goto send_var; + } - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); - 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); + if (EXPECTED(Z_ISREF_P(varptr) || + ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } - /* 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); + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } - } else { - zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); +send_var: + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); - /* 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); - } - } + 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 no value was specified yield null */ - ZVAL_NULL(&generator->value); + ZVAL_COPY_VALUE(arg, varptr); } + ZEND_VM_NEXT_OPCODE(); +} - /* Set the new yielded key */ - if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { - key = Z_REFVAL_P(key); - } - ZVAL_COPY(&generator->key, key); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; - 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); + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } } 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); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); } - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); } else { - generator->send_target = NULL; + ZVAL_MAKE_REF_EX(varptr, 2); } + ZVAL_REF(arg, Z_REF_P(varptr)); - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; - HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); - zval *result; + zval *varptr, *arg; + uint32_t arg_num; - op1 = _get_zval_ptr_var(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); - if (IS_VAR & (IS_TMP_VAR|IS_VAR)) { - zval_ptr_dtor_str(op1); + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } - ZEND_VM_SMART_BRANCH(result, 0); + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; } - if (opline->extended_value) { - if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { - result = zend_hash_index_find(ht, Z_LVAL_P(op1)); - ZEND_VM_SMART_BRANCH(result, 0); + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + 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: + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + 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(); - if ((IS_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { - op1 = Z_REFVAL_P(op1); - if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - result = zend_hash_find(ht, Z_STR_P(op1)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 0); - } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { - result = zend_hash_index_find(ht, Z_LVAL_P(op1)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + 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 if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); + } else { + ZVAL_COPY_VALUE(arg, varptr); } - } else if (Z_TYPE_P(op1) <= IS_FALSE) { - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - SAVE_OPLINE(); - ZVAL_UNDEFINED_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_CONST == IS_CONST) { + // TODO: Would it make sense to share the cache slot with CHECK_FUNC_ARG? + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } - result = zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC()); - ZEND_VM_SMART_BRANCH(result, 0); } else { - zend_string *key; - zval key_tmp; + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } - if ((IS_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { - op1 = Z_REFVAL_P(op1); - if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { - result = zend_hash_find(ht, Z_STR_P(op1)); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 0); - } + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); } + ZVAL_REF(arg, Z_REF_P(varptr)); - SAVE_OPLINE(); - ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { - ZVAL_STR(&key_tmp, key); - if (zend_compare(op1, &key_tmp) == 0) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(1, 1); - } - } ZEND_HASH_FOREACH_END(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(0, 1); + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_TMPVARCV_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; @@ -25757,7 +26910,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ SAVE_OPLINE(); do { - if (IS_VAR == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + if (IS_VAR == IS_CONST && IS_CONST == IS_CONST) { if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { value = CACHED_PTR(opline->extended_value + sizeof(void*)); break; @@ -25770,7 +26923,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ 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)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); - FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); } CACHE_PTR(opline->extended_value, ce); @@ -25779,34 +26932,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); - FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); } } else { ce = Z_CE_P(EX_VAR(opline->op1.var)); } if (IS_VAR != IS_CONST - && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST + && IS_CONST == IS_CONST && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { value = CACHED_PTR(opline->extended_value + sizeof(void*)); break; } - constant_zv = _get_zval_ptr_tmpvarcv(opline->op2_type, opline->op2, BP_VAR_R EXECUTE_DATA_CC); + constant_zv = RT_CONSTANT(opline, opline->op2); if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) { zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); ZVAL_UNDEF(EX_VAR(opline->result.var)); - FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); } constant_name = Z_STR_P(constant_zv); /* Magic 'class' for constant OP2 is caught at compile-time */ - if ((IS_TMP_VAR|IS_VAR|IS_CV) != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { + if (IS_CONST != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); - FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE(); } - zv = (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST + zv = IS_CONST == IS_CONST ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name) : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name); @@ -25816,14 +26969,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ if (!zend_verify_const_access(c, scope)) { zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); - FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); } if (ce->ce_flags & ZEND_ACC_TRAIT) { zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); - FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); } @@ -25833,7 +26986,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); - FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); } } @@ -25843,1094 +26996,911 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); - FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); } } if (Z_TYPE_P(value) == IS_CONSTANT_AST) { if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); - FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); } } - if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && !is_constant_deprecated) { + if (IS_CONST == IS_CONST && !is_constant_deprecated) { CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); } } else { zend_throw_error(NULL, "Undefined constant %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); - FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); } } while (0); ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); - FREE_OP(opline->op2_type, opline->op2.var); ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_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_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_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_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_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; - zval *value, *container, *dim; - HashTable *ht; + zval *expr_ptr, new_expr; 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); - ht = Z_ARRVAL_P(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(ht, &EG(uninitialized_zval)); - if (UNEXPECTED(!var_ptr)) { - zend_cannot_add_element(); - goto assign_dim_op_ret_null; - } + 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 { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); - } else { - var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); - } - if (UNEXPECTED(!var_ptr)) { - goto assign_dim_op_ret_null; - } + 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); - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - - do { - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; + 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); } } - 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 (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - zend_object *obj = Z_OBJ_P(container); - - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); - } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { - uint8_t old_type; + if (IS_CONST != IS_UNUSED) { + zval *offset = RT_CONSTANT(opline, opline->op2); + zend_string *str; + zend_ulong hval; - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - ht = zend_new_array(8); - old_type = Z_TYPE_P(container); - ZVAL_ARR(container, ht); - if (UNEXPECTED(old_type == IS_FALSE)) { - GC_ADDREF(ht); - zend_false_to_array_deprecated(); - if (UNEXPECTED(GC_DELREF(ht) == 0)) { - zend_array_destroy(ht); - goto assign_dim_op_ret_null; +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; } } - goto assign_dim_op_new_array; +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_safe(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 { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); -assign_dim_op_ret_null: - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); } - } - 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); + } 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_ASSIGN_OP_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; 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; - } + 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_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); + 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(); } - - 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_PRE_INC_OBJ_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 *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; + zval *container; + zval *offset; + zend_ulong hval; + zend_string *key; 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); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = 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; - } + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; -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)); +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: + ZEND_ASSERT(ht != &EG(symbol_table)); + 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_safe(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) { + zend_use_resource_as_offset(offset); + 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 { - 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); + zend_illegal_array_offset_unset(offset); + } + break; + } else if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; } - } 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); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + container = ZVAL_UNDEFINED_OP1(); + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = ZVAL_UNDEFINED_OP2(); + } + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_throw_error(NULL, "Cannot unset string offsets"); + } else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) { + zend_throw_error(NULL, "Cannot unset offset in a non-array variable"); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) { + zend_false_to_array_deprecated(); } } 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_POST_INC_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 *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; + zval *container; + zval *offset; 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); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = 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(); + 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; } - 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); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); } else { - name = zval_try_get_tmp_string(property, &tmp_name); + name = zval_try_get_tmp_string(offset, &tmp_name); if (UNEXPECTED(!name)) { - ZVAL_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) { + 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_FETCH_DIM_W_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 - zval *container; + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); 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); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - 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; + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); - 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); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); -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 + /* 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 (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_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + 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); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } else if (IS_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } } - 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)); + /* 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); } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + 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); } -} -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; + 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(); - 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(); + + ZEND_VM_RETURN(); } -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_IN_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *result; + zval *op1; + HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + zval *result; + + op1 = _get_zval_ptr_var(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); + if (IS_VAR & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + ZEND_VM_SMART_BRANCH(result, 0); + } + + if (opline->extended_value) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); + } + SAVE_OPLINE(); + if ((IS_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } else if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + } else if (Z_TYPE_P(op1) <= IS_FALSE) { + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + result = zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC()); + ZEND_VM_SMART_BRANCH(result, 0); + } else { + zend_string *key; + zval key_tmp; - SAVE_OPLINE(); + if ((IS_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } - 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 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); + SAVE_OPLINE(); + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { + ZVAL_STR(&key_tmp, key); + if (zend_compare(op1, &key_tmp) == 0) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(1, 1); + } + } ZEND_HASH_FOREACH_END(); } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(0, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + zend_class_entry *ce, *scope; + zend_class_constant *c; + zval *value, *zv, *constant_zv; + zend_string *constant_name; USE_OPLINE - zval *property, *container, *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_RW, 0 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_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif + do { + if (IS_VAR == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + } + if (IS_VAR == IS_CONST) { + 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)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->extended_value, ce); + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (IS_VAR != IS_CONST + && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST + && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } - 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)); + constant_zv = _get_zval_ptr_tmpvarcv(opline->op2_type, opline->op2, BP_VAR_R EXECUTE_DATA_CC); + if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) { + zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); } - 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)); - } -} + constant_name = Z_STR_P(constant_zv); + /* Magic 'class' for constant OP2 is caught at compile-time */ + if ((IS_TMP_VAR|IS_VAR|IS_CV) != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE(); + } + zv = (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST + ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name) + : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name); -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; + 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 constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } - 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 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} + if (ce->ce_flags & ZEND_ACC_TRAIT) { + zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_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; + bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; + if (UNEXPECTED(is_constant_deprecated)) { + zend_error(E_DEPRECATED, "Constant %s::%s is deprecated", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); - 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 (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } - 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); - } + value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { + if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && !is_constant_deprecated) { + CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); + } + } else { + zend_throw_error(NULL, "Undefined constant %s::%s", + ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } while (0); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + + FREE_OP(opline->op2_type, opline->op2.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_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; + zval *var_ptr; + zval *value, *container, *dim; + HashTable *ht; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = RT_CONSTANT((opline+1), (opline+1)->op1); + container = _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; + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(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(ht, &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } } - zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) 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) { - if (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); - 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)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } - } else { - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; - } - } + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; + 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); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { - name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - - 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; + } } - } - - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - ZVAL_DEREF(value); - } - value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); - } + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + uint8_t old_type; -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } + } + goto assign_dim_op_new_array; + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } } -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); - } 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_TMP_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 *object, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; + zval *var_ptr; + zval *value; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - 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, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) 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) { - if (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); - 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)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } - } else { - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; - } - } + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + 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; } } - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); - } else { - name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; - } - } - - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(value); - } - - value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zend_tmp_string_release(tmp_name); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); - } 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_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *value, tmp; + zval *object; + zval *property; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; zend_object *zobj; zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.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, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) 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) { - if (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); - 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)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); - 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_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 { - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; - } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + } else { + prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); } - if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); } - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); - } else { - name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } - } - - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(value); - } - - 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); - } + } while (0); -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); - } 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_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; + zval *container; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.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; - } - zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} -assign_object: - zobj = Z_OBJ_P(object); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - if (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); - zval *property_val; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_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, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } - } else { - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; - } - } +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 (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - 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)); } - name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - - UNDEF_RESULT(); - goto exit_assign_obj; + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } +} - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(value); +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(); +} - 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_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; - 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); + 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 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(); +} -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim; -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); + 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)); - 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) { USE_OPLINE @@ -27325,188 +28295,36 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ dim++; } - value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { - value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); - } else if (IS_VAR & (IS_CV|IS_VAR)) { - ZVAL_DEREF(value); - } - - zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); - - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - if (UNEXPECTED(GC_DELREF(obj) == 0)) { - zend_objects_store_del(obj); - } - } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { - 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 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((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 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - } else { - HashTable *ht = zend_new_array(8); - uint8_t old_type = Z_TYPE_P(object_ptr); - - ZVAL_ARR(object_ptr, ht); - if (UNEXPECTED(old_type == IS_FALSE)) { - GC_ADDREF(ht); - zend_false_to_array_deprecated(); - if (UNEXPECTED(GC_DELREF(ht) == 0)) { - zend_array_destroy(ht); - goto assign_dim_error; - } - } - goto try_assign_dim_array; - } - } else { - zend_use_scalar_as_array(); - 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))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } - } - 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_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zval *value; - zval *variable_ptr; - zval *dim; - zend_refcounted *garbage = NULL; - - 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_TMP_VAR|IS_VAR) == IS_UNUSED) { - value = EX_VAR((opline+1)->op1.var); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - HashTable *ht = Z_ARRVAL_P(object_ptr); - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(ht); - } - value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { - zend_array_destroy(ht); - goto assign_dim_error; - } - } - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(value); - } - value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); - if (UNEXPECTED(value == NULL)) { - 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 (Z_ISREF_P(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 = _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); - } - 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_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (garbage) { - GC_DTOR_NO_REF(garbage); - } - } 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)) { - zend_object *obj = Z_OBJ_P(object_ptr); - - GC_ADDREF(obj); - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { - dim = ZVAL_UNDEFINED_OP2(); - } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { - dim++; - } - - value = EX_VAR((opline+1)->op1.var); - if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); - } else if (IS_CV & (IS_CV|IS_VAR)) { + } else if (IS_VAR & (IS_CV|IS_VAR)) { ZVAL_DEREF(value); } zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { 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 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = EX_VAR((opline+1)->op1.var); + value = _get_zval_ptr_var((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 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -27527,7 +28345,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zend_use_scalar_as_array(); 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))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -27541,80 +28359,158 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ 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_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - 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); + 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) { + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + 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 (Z_ISREF_P(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 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { - zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + 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_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); } } else { - zend_assign_to_property_reference(container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); - } + 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)) { + zend_object *obj = Z_OBJ_P(object_ptr); - 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); -} + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } -/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *property, *container, *value_ptr; + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } - SAVE_OPLINE(); + zend_assign_to_object_dim(obj, dim, value OPLINE_CC 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); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_use_new_element_for_string(); - value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + UNDEF_RESULT(); + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC 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 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 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + UNDEF_RESULT(); } else { - zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; } } 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); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } } - } else { - zend_assign_to_property_reference(container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - + 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)); - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - + /* assign_dim 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_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -28515,7 +29411,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UN if (IS_UNUSED == IS_UNUSED) { ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } } @@ -30082,190 +30978,93 @@ 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) -{ - USE_OPLINE - zval *op1 = EX_VAR(opline->op1.var); - - 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); - } - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1; - zend_string *type; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - type = zend_zval_get_legacy_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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED_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_UNUSED_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_CASE_STRICT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - - ZEND_VM_SMART_BRANCH(result, 1); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_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 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - - 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_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; - - do { - if (UNEXPECTED(Z_ISREF_P(zptr))) { - ref = Z_REF_P(zptr); - zptr = Z_REFVAL_P(zptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - } - - if (IS_CV == IS_CONST) { - prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr); - } - if (UNEXPECTED(prop_info)) { - /* special case for typed properties */ - zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_binary_op(zptr, zptr, value OPLINE_CC); - } - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1 = EX_VAR(opline->op1.var); + + 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 { - zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + 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)); } - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); + } 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)); } - } while (0); + 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(); +} - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_string *type; + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + type = zend_zval_get_legacy_type(op1); + if (EXPECTED(type)) { + ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); + } else { + ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED_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_UNUSED_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_CASE_STRICT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + + ZEND_VM_SMART_BRANCH(result, 1); } -/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -30350,879 +31149,221 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND goto assign_dim_op_ret_null; } } - goto assign_dim_op_new_array; - } else { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); -assign_dim_op_ret_null: - FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - 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_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; - } - } - 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_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - do { - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto pre_incdec_object; - } - if (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_CV == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - UNDEF_RESULT(); - break; - } - } - cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - if (IS_CV == IS_CONST) { - prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); - } - zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); - } - } 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_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *object; - zval *property; - zval *zptr; - void **cache_slot; - zend_property_info *prop_info; - zend_object *zobj; - zend_string *name, *tmp_name; - - SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - do { - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { - object = Z_REFVAL_P(object); - goto post_incdec_object; - } - if (IS_VAR == IS_CV - && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); - break; - } - -post_incdec_object: - /* here we are sure we are dealing with an object */ - zobj = Z_OBJ_P(object); - if (IS_CV == IS_CONST) { - name = Z_STR_P(property); - } else { - name = zval_try_get_tmp_string(property, &tmp_name); - if (UNEXPECTED(!name)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - break; - } - } - cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { - if (UNEXPECTED(Z_ISERROR_P(zptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { - if (IS_CV == IS_CONST) { - prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); - } else { - prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); - } - - zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); - } - } else { - zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); - } - if (IS_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(); -} - -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(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif - - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - if (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)); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); - - 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_CV_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 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_CV_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) : NULL), BP_VAR_RW, 0 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_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 - USE_OPLINE -#endif - - if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - /* Behave like FETCH_OBJ_W */ - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { - ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } else { - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *property, *result; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - result = EX_VAR(opline->result.var); - 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 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_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container, *dim; - - SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - dim = EX_VAR(opline->op2.var); - - if (IS_VAR == IS_VAR - && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT - && UNEXPECTED(!Z_ISREF_P(container)) - ) { - zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); - zend_fetch_dimension_address_LIST_r(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); - } else { - zend_fetch_dimension_address_W(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); - } - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *object, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; - - SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.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; - } - zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) 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) { - if (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); - 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)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } - } else { - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; - } - } - - if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + goto assign_dim_op_new_array; + } else { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } } - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); - } else { - name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - - UNDEF_RESULT(); - goto exit_assign_obj; - } } - if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - ZVAL_DEREF(value); - } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} - 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_ASSIGN_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value; - if (IS_CV != IS_CONST) { - zend_tmp_string_release(tmp_name); - } + 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); -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); + 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_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_TMP_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, *value, tmp; + zval *object; + zval *property; + zval *zptr; + void **cache_slot; + zend_property_info *prop_info; zend_object *zobj; zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->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); - 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, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) 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) { - if (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); - 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)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); - 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 { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } else { - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; - } + 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); } - if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); } - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); - } else { - name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } - } + } while (0); - if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - ZVAL_DEREF(value); - } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + 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_FETCH_DIM_W_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_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* 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_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; + zval *container; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + 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_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, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) 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_CV == IS_CONST) { - if (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); - 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)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } - } else { - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; - } - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif - if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - 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)); } - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { - name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); - UNDEF_RESULT(); - goto exit_assign_obj; + if (IS_CV == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } +} - if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - ZVAL_DEREF(value); - } - - 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); -free_and_exit_assign_obj: - if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } - - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* 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_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *value, tmp; - zend_object *zobj; - zend_string *name, *tmp_name; - zend_refcounted *garbage = NULL; + zval *container, *property, *result; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.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); + 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 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, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) 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_CV == IS_CONST) { - if (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); - 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_FETCH_LIST_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim; - if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { -fast_assign_obj: - value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } - } else { - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(zobj->properties); - } - zobj->properties = zend_array_dup(zobj->properties); - } - property_val = zend_hash_find_known_hash(zobj->properties, name); - if (property_val) { - goto fast_assign_obj; - } - } + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = EX_VAR(opline->op2.var); - if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { - 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, name, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - goto exit_assign_obj; - } - } - } - name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(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_CV OPLINE_CC EXECUTE_DATA_CC); } else { - name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); - if (UNEXPECTED(!name)) { - - UNDEF_RESULT(); - goto exit_assign_obj; - } - } - - if (IS_CV == IS_CV || IS_CV == IS_VAR) { - ZVAL_DEREF(value); - } - - 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)) && value) { - ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); - } - -exit_assign_obj: - if (garbage) { - GC_DTOR_NO_REF(garbage); + zend_fetch_dimension_address_W(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); } - 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_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -31929,80 +32070,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 @@ -33037,7 +33104,7 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R zval *retval; if (IS_CONST == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -33151,7 +33218,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 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(); @@ -33168,7 +33235,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 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(); @@ -33294,7 +33361,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)); @@ -35096,7 +35163,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -35205,7 +35272,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 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(); @@ -35222,7 +35289,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 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(); @@ -35348,7 +35415,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)); @@ -37602,7 +37669,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN zval *retval; if (IS_CV == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -37711,7 +37778,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 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(); @@ -37728,7 +37795,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 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(); @@ -37854,7 +37921,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)); @@ -41735,7 +41802,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HAND container = EX_VAR(opline->op1.var); dim = RT_CONSTANT(opline, opline->op2); if (IS_CV != IS_CONST) { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R EXECUTE_DATA_CC); ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); @@ -41748,12 +41815,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HAND } } else { fetch_dim_r_slow: + if (IS_CONST == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } 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); } } else { + if (IS_CONST == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); } @@ -41872,7 +41945,7 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R zval *retval; if (IS_CONST == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -41986,7 +42059,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 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(); @@ -42003,7 +42076,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 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(); @@ -42129,7 +42202,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)); @@ -45579,7 +45652,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HAN container = EX_VAR(opline->op1.var); dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CV != IS_CONST) { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R EXECUTE_DATA_CC); ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); @@ -45592,12 +45665,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HAN } } else { fetch_dim_r_slow: + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } if ((IS_TMP_VAR|IS_VAR) == 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 { + 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_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -45716,7 +45795,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -45825,7 +45904,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 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(); @@ -45842,7 +45921,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 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(); @@ -45968,7 +46047,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)); @@ -48528,6 +48607,47 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLE } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + dim = NULL; + if (IS_CV != IS_CONST) { + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_UNUSED, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if (IS_UNUSED == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + if (IS_UNUSED == 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 { + if (IS_UNUSED == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + zend_fetch_dimension_address_read_R(container, dim, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -48573,7 +48693,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNU if (IS_UNUSED == IS_UNUSED) { ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } } @@ -50970,7 +51090,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER container = EX_VAR(opline->op1.var); dim = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + if (IS_CV != IS_UNUSED && 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); @@ -50983,12 +51103,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER } } else { fetch_dim_r_slow: + if (IS_CV == IS_UNUSED && Z_TYPE_P(container) != IS_OBJECT) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } 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 { + if (IS_CV == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); } @@ -51107,7 +51233,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER zval *retval; if (IS_CV == IS_CONST) { - cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS /* 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); @@ -51216,7 +51342,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 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(); @@ -51233,7 +51359,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 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(); @@ -51359,7 +51485,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)); @@ -54487,56 +54613,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, @@ -54647,16 +54773,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, @@ -54725,13 +54851,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, @@ -54739,40 +54871,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_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (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_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, @@ -55200,17 +55326,17 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_FETCH_DIM_R_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_LABEL, - (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_FETCH_DIM_R_SPEC_CONST_UNUSED_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_CONST_CV_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_LABEL, - (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -55220,7 +55346,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_FETCH_DIM_R_SPEC_CV_CONST_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_LABEL, - (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_FETCH_DIM_R_SPEC_CV_UNUSED_LABEL, (void*)&&ZEND_FETCH_DIM_R_SPEC_CV_CV_LABEL, (void*)&&ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_LABEL, @@ -55282,16 +55408,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, @@ -55337,16 +55463,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, @@ -55447,16 +55573,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, @@ -55805,16 +55931,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, @@ -58434,6 +58560,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_IS_SPEC_CONST_UNUSED) HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_DIM_R_SPEC_CONST_UNUSED): + VM_TRACE(ZEND_FETCH_DIM_R_SPEC_CONST_UNUSED) + ZEND_FETCH_DIM_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FETCH_DIM_R_SPEC_CONST_UNUSED) + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED): VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED) ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -59294,6 +59425,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_BOOL_XOR_SPEC_TMPVAR_CONST) 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CONST) + 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); + VM_TRACE_OP_END(ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST) + 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); @@ -59309,11 +59450,56 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST) 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); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST) + 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); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST) + 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); VM_TRACE_OP_END(ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST) 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); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CONST) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_TMP) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_VAR) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CONST_OP_DATA_CV) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_VAR) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CONST_OP_DATA_CV) + 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); @@ -59419,6 +59605,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR) 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_TMPVAR) + 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); + VM_TRACE_OP_END(ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR) + 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); @@ -59434,11 +59630,56 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR) 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); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR) + 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); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR) + 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); VM_TRACE_OP_END(ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR) 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); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CONST) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_TMP) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_VAR) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_TMPVAR_OP_DATA_CV) + 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); @@ -59504,6 +59745,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED) HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED): + VM_TRACE(ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED) + ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED) + HYBRID_BREAK(); HYBRID_CASE(ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED): VM_TRACE(ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED) ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -59564,6 +59810,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_SPACESHIP_SPEC_TMPVAR_CV) 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_OP_SPEC_TMPVAR_CV) + 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); + VM_TRACE_OP_END(ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV) + 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); @@ -59579,11 +59835,56 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV) 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); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV) + 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); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV) + 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); VM_TRACE_OP_END(ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV) 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); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CONST) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_TMP) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_VAR) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_TMPVAR_CV_OP_DATA_CV) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_VAR) + 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); + VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_TMPVAR_CV_OP_DATA_CV) + 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); @@ -59768,11 +60069,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST) 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST) - 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); @@ -59813,11 +60109,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR) 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR) - 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); @@ -59913,11 +60204,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV) 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV) - 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); @@ -60137,11 +60423,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST) 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST) - 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); @@ -60152,11 +60433,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_ASSIGN_OP_SPEC_VAR_CONST) 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); - VM_TRACE_OP_END(ZEND_PRE_INC_OBJ_SPEC_VAR_CONST) - 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); @@ -60182,21 +60458,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST) 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_W_SPEC_VAR_CONST) - 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST) - 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST) - 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); @@ -60207,26 +60468,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_LIST_W_SPEC_VAR_CONST) 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV) - 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); @@ -60257,16 +60498,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED) 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV) - 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); @@ -60342,11 +60573,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_TMPVARCV) 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR) - 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); @@ -60357,11 +60583,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR) 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); - VM_TRACE_OP_END(ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR) - 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); @@ -60387,21 +60608,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR) 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR) - 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR) - 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR) - 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); @@ -60412,26 +60618,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR) 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV) - 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); @@ -60452,16 +60638,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV) 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV) - 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); @@ -60682,11 +60858,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_CASE_STRICT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_CASE_STRICT_SPEC_VAR_CV) 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV) - 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); @@ -60697,11 +60868,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_ASSIGN_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_ASSIGN_OP_SPEC_VAR_CV) 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); - VM_TRACE_OP_END(ZEND_PRE_INC_OBJ_SPEC_VAR_CV) - 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); @@ -60727,21 +60893,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV) 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_W_SPEC_VAR_CV) - 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_RW_SPEC_VAR_CV) - 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); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV) - 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); @@ -60752,26 +60903,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_LIST_W_SPEC_VAR_CV) 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV) - 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); @@ -60807,16 +60938,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_ASSIGN_REF_SPEC_VAR_CV) 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR) - 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); - VM_TRACE_OP_END(ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV) - 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); @@ -62266,6 +62387,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FETCH_IS_SPEC_CV_UNUSED) HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_DIM_R_SPEC_CV_UNUSED): + VM_TRACE(ZEND_FETCH_DIM_R_SPEC_CV_UNUSED) + ZEND_FETCH_DIM_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FETCH_DIM_R_SPEC_CV_UNUSED) + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_DIM_W_SPEC_CV_UNUSED): VM_TRACE(ZEND_FETCH_DIM_W_SPEC_CV_UNUSED) ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -63644,56 +63770,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, @@ -63804,16 +63930,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, @@ -63882,13 +64008,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, @@ -63896,40 +64028,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_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_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, @@ -64357,17 +64483,17 @@ void zend_vm_init(void) ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER, ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER, ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_UNUSED_HANDLER, ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER, ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER, ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER, ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER, ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -64377,7 +64503,7 @@ void zend_vm_init(void) ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER, ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER, ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CV_UNUSED_HANDLER, ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER, ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER, ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER, @@ -64439,16 +64565,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, @@ -64494,16 +64620,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, @@ -64604,16 +64730,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, @@ -64962,16 +65088,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, @@ -66888,7 +67014,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t } break; case ZEND_FETCH_DIM_R: - if (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) { + if ((op->op2_type != IS_UNDEF) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 60a4a7336b48e..0a41cf64980f9 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -78,6 +78,7 @@ "ZEND_VM_EXT_REF" => 1<<20, "ZEND_VM_EXT_FETCH_REF" => 1<<21, "ZEND_VM_EXT_DIM_WRITE" => 1<<22, + "ZEND_VM_EXT_OBJ_W_CONTAINER" => 1<<23, "ZEND_VM_EXT_MASK" => 0x0f000000, "ZEND_VM_EXT_NUM" => 0x01000000, "ZEND_VM_EXT_LAST_CATCH" => 0x02000000, @@ -135,6 +136,7 @@ "SRC" => ZEND_VM_EXT_SRC, "CACHE_SLOT" => ZEND_VM_EXT_CACHE_SLOT, "DIM_WRITE" => ZEND_VM_EXT_DIM_WRITE, + "OBJ_W_CONTAINER" => ZEND_VM_EXT_OBJ_W_CONTAINER, ); $vm_kind_name = array( diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 90b26caf88439..c22f1054b8589 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) \ @@ -759,18 +787,22 @@ _(1596, ZEND_FETCH_DIM_R_SPEC_CONST_CONST) \ _(1597, ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR) \ _(1598, ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR) \ + _(1599, ZEND_FETCH_DIM_R_SPEC_CONST_UNUSED) \ _(1600, ZEND_FETCH_DIM_R_SPEC_CONST_CV) \ _(1601, ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST) \ _(1602, ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR) \ _(1603, ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR) \ + _(1604, ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED) \ _(1605, ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV) \ _(1606, ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST) \ _(1607, ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR) \ _(1608, ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR) \ + _(1609, ZEND_FETCH_DIM_R_SPEC_TMPVAR_UNUSED) \ _(1610, ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV) \ _(1616, ZEND_FETCH_DIM_R_SPEC_CV_CONST) \ _(1617, ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR) \ _(1618, ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR) \ + _(1619, ZEND_FETCH_DIM_R_SPEC_CV_UNUSED) \ _(1620, ZEND_FETCH_DIM_R_SPEC_CV_CV) \ _(1621, ZEND_FETCH_OBJ_R_SPEC_CONST_CONST) \ _(1622, ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR) \ @@ -806,10 +838,14 @@ _(1673, ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR) \ _(1674, ZEND_FETCH_DIM_W_SPEC_CV_UNUSED) \ _(1675, ZEND_FETCH_DIM_W_SPEC_CV_CV) \ - _(1686, ZEND_FETCH_OBJ_W_SPEC_VAR_CONST) \ - _(1687, ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR) \ - _(1688, ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR) \ - _(1690, ZEND_FETCH_OBJ_W_SPEC_VAR_CV) \ + _(1681, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST) \ + _(1682, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR) \ + _(1683, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR) \ + _(1685, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV) \ + _(1686, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CONST) \ + _(1687, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR) \ + _(1688, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_TMPVAR) \ + _(1690, ZEND_FETCH_OBJ_W_SPEC_TMPVAR_CV) \ _(1691, ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST) \ _(1692, ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR) \ _(1693, ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR) \ @@ -832,10 +868,14 @@ _(1728, ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR) \ _(1729, ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED) \ _(1730, ZEND_FETCH_DIM_RW_SPEC_CV_CV) \ - _(1741, ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST) \ - _(1742, ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR) \ - _(1743, ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR) \ - _(1745, ZEND_FETCH_OBJ_RW_SPEC_VAR_CV) \ + _(1736, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST) \ + _(1737, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR) \ + _(1738, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR) \ + _(1740, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV) \ + _(1741, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CONST) \ + _(1742, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR) \ + _(1743, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_TMPVAR) \ + _(1745, ZEND_FETCH_OBJ_RW_SPEC_TMPVAR_CV) \ _(1746, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST) \ _(1747, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR) \ _(1748, ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR) \ @@ -912,14 +952,14 @@ _(1842, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR) \ _(1843, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR) \ _(1845, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV) \ - _(1846, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST) \ - _(1847, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR) \ - _(1848, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR) \ - _(1850, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV) \ - _(1851, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST) \ - _(1852, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR) \ - _(1853, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR) \ - _(1855, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV) \ + _(1846, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST) \ + _(1847, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR) \ + _(1848, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR) \ + _(1850, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV) \ + _(1851, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CONST) \ + _(1852, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR) \ + _(1853, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_TMPVAR) \ + _(1855, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMPVAR_CV) \ _(1856, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST) \ _(1857, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR) \ _(1858, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR) \ @@ -1115,10 +1155,14 @@ _(2196, ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED) \ _(2197, ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER) \ _(2198, ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER) \ - _(2209, ZEND_PRE_INC_OBJ_SPEC_VAR_CONST) \ - _(2210, ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR) \ - _(2211, ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR) \ - _(2213, ZEND_PRE_INC_OBJ_SPEC_VAR_CV) \ + _(2204, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST) \ + _(2205, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR) \ + _(2206, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR) \ + _(2208, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV) \ + _(2209, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CONST) \ + _(2210, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR) \ + _(2211, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_TMPVAR) \ + _(2213, ZEND_PRE_INC_OBJ_SPEC_TMPVAR_CV) \ _(2214, ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST) \ _(2215, ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR) \ _(2216, ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR) \ diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 218a55a8f4e8b..5177a60a43a55 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -259,15 +259,15 @@ static uint32_t zend_vm_opcodes_flags[209] = { 0x00000b0b, 0x00000301, 0x00006701, - 0x00040751, + 0x00040755, 0x00040000, 0x04000701, 0x04006701, - 0x04000751, + 0x04000755, 0x04000000, 0x0b000101, 0x00000003, - 0x0b040751, + 0x0b040755, 0x0b040000, 0x00000001, 0x00000001, @@ -316,20 +316,20 @@ static uint32_t zend_vm_opcodes_flags[209] = { 0x03000001, 0x00000000, 0x00010107, - 0x00000707, - 0x00040757, + 0x00806707, + 0x00840757, 0x00010107, 0x00006701, - 0x00640751, + 0x00640755, 0x00010107, 0x00006701, - 0x00040751, + 0x00040755, 0x00010107, 0x00000707, 0x00040757, 0x00010107, 0x00006703, - 0x00240753, + 0x00240757, 0x00010107, 0x00000701, 0x00040751, @@ -367,7 +367,7 @@ static uint32_t zend_vm_opcodes_flags[209] = { 0x00000000, 0x00000000, 0x00000000, - 0x00040751, + 0x00040755, 0x00040751, 0x00040751, 0x00040751, diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index a273a9b7e2de0..748191aa20c0b 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -61,6 +61,7 @@ #define ZEND_VM_EXT_REF 0x00100000 #define ZEND_VM_EXT_FETCH_REF 0x00200000 #define ZEND_VM_EXT_DIM_WRITE 0x00400000 +#define ZEND_VM_EXT_OBJ_W_CONTAINER 0x00800000 #define ZEND_VM_EXT_MASK 0x0f000000 #define ZEND_VM_EXT_NUM 0x01000000 #define ZEND_VM_EXT_LAST_CATCH 0x02000000 diff --git a/ext/opcache/tests/opt/inference_004.phpt b/ext/opcache/tests/opt/inference_004.phpt index 377cef95d7cbe..1bb413281a660 100644 --- a/ext/opcache/tests/opt/inference_004.phpt +++ b/ext/opcache/tests/opt/inference_004.phpt @@ -14,5 +14,5 @@ function y() { } ?> DONE ---EXPECT-- -DONE +--EXPECTF-- +Fatal error: Cannot use [] for reading in %s on line %d diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index a66b31a499b99..8c2169ab0238e 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -185,6 +185,8 @@ static xmlNodePtr sxe_get_element_by_name(php_sxe_object *sxe, xmlNodePtr node, } /* }}} */ +static zval *sxe_property_get_adr(zend_object *object, zend_string *zname, int fetch_type, void **cache_slot); + /* {{{ sxe_prop_dim_read() */ static zval *sxe_prop_dim_read(zend_object *object, zval *member, bool elements, bool attribs, int type, zval *rv) { @@ -196,6 +198,16 @@ static zval *sxe_prop_dim_read(zend_object *object, zval *member, bool elements, int nodendx = 0; int test = 0; + /* BC layer: The lhs of -> is fetched by R. However, SimpleXML still supports auto-vivification. + * Switch to W on the fly. */ + zend_execute_data *execute_data = EG(current_execute_data); + bool switch_to_w = type == BP_VAR_R + && (EX(opline)->opcode == ZEND_FETCH_OBJ_R || EX(opline)->opcode == ZEND_FETCH_DIM_R) + && (EX(opline)->extended_value & ZEND_FETCH_OBJ_FLAGS) == ZEND_FETCH_OBJ_W_CONTAINER; + if (switch_to_w) { + type = BP_VAR_W; + } + sxe = php_sxe_fetch_object(object); if (!member) { @@ -223,6 +235,12 @@ static zval *sxe_prop_dim_read(zend_object *object, zval *member, bool elements, ZVAL_STR(&tmp_zv, str); member = &tmp_zv; } + if (switch_to_w) { + zval *result = sxe_property_get_adr(object, Z_STR_P(member), BP_VAR_W, NULL); + if (result) { + return result; + } + } name = Z_STRVAL_P(member); } } diff --git a/ext/simplexml/tests/bug41582.phpt b/ext/simplexml/tests/bug41582.phpt index f611310485d71..a37a9497849b5 100644 --- a/ext/simplexml/tests/bug41582.phpt +++ b/ext/simplexml/tests/bug41582.phpt @@ -9,10 +9,12 @@ $xml = new SimpleXMLElement(' '); $xml->movie[]->characters->character[0]->name = 'Miss Coder'; +$movie = $xml->movie[0]; +$movie->characters->character[1]->name = 'Mr Bug'; echo($xml->asXml()); ?> --EXPECT-- -Miss Coder +Miss CoderMr Bug