From 58d9397c6650a0360456375b698fdcc622acd09f Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 10 Nov 2019 17:01:21 -0500 Subject: [PATCH 1/5] Improve performance of ZEND_IS_IDENTICAL And for ZEND_IS_NOT_IDENTICAL. - Take advantage of branch prediction in cases that are false/true - Avoid function call and duplicate fetches of Z_TYPE_P in common use cases - Avoid checking for EG(exception) when it's impossible. I think that the zval would always be IS_NULL or lower for an exception, but may be wrong. Aside 1: I see that ZEND_IS_EQUAL does have the `SMART_BRANCH` in the `SPEC`, generating optimized implementations based on what type of smart branch is used. Is excluding it from ZEND_IS_IDENTICAL deliberate, and if so, what's the reasoning? (e.g. is the use in common applications low?) - The SMART_BRANCH specialization was introduced in 27e01cd918dd3309571aa3628e6139d436b10e18 Aside 2: The function pointer for ZEND_IS_EQUAL_LONG can probably be used directly for ZEND_IS_IDENTICAL_LONG. I'm not sure how to generate that. (and DOUBLE) The amount of time for nestedloop_ni(20) decreased from 0.726s to 0.593s due to this change. This is still worse than `!=` (0.434) and `<` (0.375), which have implementations that take advantage of branch prediction for IS_LONG ```php function nestedloop_ni($n) { $x = 0; for ($a=0; $a!==$n; $a++) for ($b=0; $b!==$n; $b++) for ($c=0; $c!==$n; $c++) for ($d=0; $d!==$n; $d++) for ($e=0; $e!==$n; $e++) for ($f=0; $f!==$n; $f++) $x++; print "$x\n"; } ``` --- Zend/tests/bug70785.phpt | 5 + Zend/zend_operators.c | 6 + Zend/zend_operators.h | 1 + Zend/zend_vm_def.h | 101 ++++- Zend/zend_vm_execute.h | 870 ++++++++++++++++++++++++++++++++++++--- 5 files changed, 921 insertions(+), 62 deletions(-) diff --git a/Zend/tests/bug70785.phpt b/Zend/tests/bug70785.phpt index f48bc3cdb99e..0a8581bd9c09 100644 --- a/Zend/tests/bug70785.phpt +++ b/Zend/tests/bug70785.phpt @@ -19,6 +19,11 @@ try { undefined_function(); } catch (Exception $e) { } +try { + $d === $f; // ZEND_VM_NEXT_OPCODE + undefined_function(); +} catch (Exception $e) { +} ?> okey --EXPECT-- diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index a1f3024d4e9b..7214b87ccb12 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2118,6 +2118,12 @@ ZEND_API zend_bool ZEND_FASTCALL zend_is_identical(zval *op1, zval *op2) /* {{{ } /* }}} */ +ZEND_API zend_bool ZEND_FASTCALL zend_is_identical_array(HashTable *h1, HashTable *h2) /* {{{ */ +{ + return (h1 == h2 || + zend_hash_compare(h1, h2, (compare_func_t) hash_zval_identical_function, 1) == 0); +} + ZEND_API int ZEND_FASTCALL is_identical_function(zval *result, zval *op1, zval *op2) /* {{{ */ { ZVAL_BOOL(result, zend_is_identical(op1, op2)); diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index ee7c951c7d51..2a7bd0a94102 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -55,6 +55,7 @@ ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *o ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2); ZEND_API zend_bool ZEND_FASTCALL zend_is_identical(zval *op1, zval *op2); +ZEND_API zend_bool ZEND_FASTCALL zend_is_identical_array(HashTable *h1, HashTable *h2); ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2); ZEND_API int ZEND_FASTCALL is_identical_function(zval *result, zval *op1, zval *op2); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index a8ab1ff375c4..6c6087b7c114 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -451,25 +451,102 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T SAVE_OPLINE(); op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); - result = fast_is_identical_function(op1, op2); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + ZEND_VM_C_LABEL(is_different_nothrow): + FREE_OP1(); + FREE_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + FREE_OP1(); + FREE_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + ZEND_VM_C_GOTO(is_different_nothrow); + } FREE_OP1(); FREE_OP2(); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE)) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); - result = fast_is_not_identical_function(op1, op2); + + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + ZEND_VM_C_LABEL(is_different_nothrow): + FREE_OP1(); + FREE_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + FREE_OP1(); + FREE_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + ZEND_VM_C_GOTO(is_different_nothrow); + } FREE_OP1(); FREE_OP2(); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } ZEND_VM_HELPER(zend_is_equal_helper, ANY, ANY, zval *op_1, zval *op_2) @@ -1496,7 +1573,7 @@ ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY) SAVE_OPLINE(); if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { - ZVAL_NULL(var_ptr); + ZVAL_NULL(var_ptr); ZVAL_UNDEFINED_OP1(); } @@ -2234,7 +2311,7 @@ ZEND_VM_C_LABEL(fetch_obj_is_fast_copy): } retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); - + if (OP2_TYPE != IS_CONST) { zend_tmp_string_release(tmp_name); } @@ -5528,10 +5605,10 @@ ZEND_VM_HANDLER(147, ZEND_ADD_ARRAY_UNPACK, ANY, ANY) { USE_OPLINE zval *op1; - + SAVE_OPLINE(); op1 = GET_OP1_ZVAL_PTR(BP_VAR_R); - + ZEND_VM_C_LABEL(add_unpack_again): if (EXPECTED(Z_TYPE_P(op1) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(op1); @@ -5572,11 +5649,11 @@ ZEND_VM_C_LABEL(add_unpack_again): } HANDLE_EXCEPTION(); } - + if (iter->funcs->rewind) { iter->funcs->rewind(iter); } - + for (; iter->funcs->valid(iter) == SUCCESS; ) { zval *val; @@ -5625,7 +5702,7 @@ ZEND_VM_C_LABEL(add_unpack_again): } else { zend_throw_error(NULL, "Only arrays and Traversables can be unpacked"); } - + FREE_OP1(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 5da5452b69be..89fb5b19ae9b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4763,25 +4763,102 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); op2 = RT_CONSTANT(opline, opline->op2); - result = fast_is_identical_function(op1, op2); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + + + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } + + + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); op2 = RT_CONSTANT(opline, opline->op2); - result = fast_is_not_identical_function(op1, op2); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: - ZEND_VM_SMART_BRANCH(result, 1); + + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + + + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } + + + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17799,25 +17876,102 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA 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); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); - result = fast_is_not_identical_function(op1, op2); + + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -18600,25 +18754,102 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND 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); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); + + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -20809,25 +21040,102 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA 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); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); - result = fast_is_not_identical_function(op1, op2); + + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -25180,25 +25488,102 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND SAVE_OPLINE(); op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); + + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -25250,25 +25635,102 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND SAVE_OPLINE(); op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); + + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -36729,25 +37191,102 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); - result = fast_is_identical_function(op1, op2); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + + + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } + + + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); - result = fast_is_not_identical_function(op1, op2); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: - ZEND_VM_SMART_BRANCH(result, 1); + + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + + + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } + + + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -43207,25 +43746,102 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(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); + + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -43277,25 +43893,102 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(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); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); + + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -44932,25 +45625,102 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(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); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return true */ + + + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) == Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + break; + case IS_STRING: + result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } + + + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ + is_different_nothrow: - ZEND_VM_SMART_BRANCH(result, 1); + + ZEND_VM_SMART_BRANCH(1, 1); + return; + } + if (Z_TYPE_P(op1) <= IS_TRUE) { + /* They are identical, return false */ + + + ZEND_VM_SMART_BRANCH(0, 1); + return; + } + switch (Z_TYPE_P(op1)) { + case IS_LONG: + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + break; + case IS_RESOURCE: + result = (Z_RES_P(op1) != Z_RES_P(op2)); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + break; + case IS_STRING: + result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); + break; + case IS_ARRAY: + /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ + /* XXX hash_zval_identical_function is not static */ + result = !zend_is_identical_array(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2)); + break; + case IS_OBJECT: + result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); + break; + default: + goto is_different_nothrow; + } + + + ZEND_VM_SMART_BRANCH(result, 0); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) From 72ec3a6753923243105f430a676995fc36398953 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Mon, 11 Nov 2019 08:39:53 -0500 Subject: [PATCH 2/5] Address review feedback --- Zend/zend_vm_def.h | 38 +++-- Zend/zend_vm_execute.h | 370 ++++++++++++++++++++++++++--------------- 2 files changed, 259 insertions(+), 149 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6c6087b7c114..196cb7d3854d 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -452,8 +452,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - ZEND_VM_C_LABEL(is_different_nothrow): + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(0, 1); @@ -461,6 +460,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(1, 1); @@ -469,16 +469,20 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +ZEND_VM_C_LABEL(free_nothrow): + FREE_OP1(); + FREE_OP2(); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + ZEND_VM_C_GOTO(free_nothrow); case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + ZEND_VM_C_GOTO(free_nothrow); case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -488,11 +492,12 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - ZEND_VM_C_GOTO(is_different_nothrow); + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ FREE_OP1(); FREE_OP2(); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE)) @@ -506,15 +511,15 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CON op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - ZEND_VM_C_LABEL(is_different_nothrow): - FREE_OP1(); + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(0, 1); @@ -523,16 +528,20 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CON switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +ZEND_VM_C_LABEL(free_nothrow): + FREE_OP1(); + FREE_OP2(); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + ZEND_VM_C_GOTO(free_nothrow); case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + ZEND_VM_C_GOTO(free_nothrow); case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -542,11 +551,12 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CON result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - ZEND_VM_C_GOTO(is_different_nothrow); + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ FREE_OP1(); FREE_OP2(); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } ZEND_VM_HELPER(zend_is_equal_helper, ANY, ANY, zval *op_1, zval *op_2) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 89fb5b19ae9b..f26f68286032 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4764,8 +4764,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC op1 = RT_CONSTANT(opline, opline->op1); op2 = RT_CONSTANT(opline, opline->op2); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ ZEND_VM_SMART_BRANCH(0, 1); @@ -4773,6 +4772,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ ZEND_VM_SMART_BRANCH(1, 1); @@ -4781,16 +4781,20 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +free_nothrow: + + + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -4800,11 +4804,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -4818,15 +4823,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_ op2 = RT_CONSTANT(opline, opline->op2); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ ZEND_VM_SMART_BRANCH(0, 1); @@ -4835,16 +4840,20 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_ switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +free_nothrow: + + + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -4854,11 +4863,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_ result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17877,8 +17887,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -17886,6 +17895,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(1, 1); @@ -17894,16 +17904,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +free_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -17913,11 +17927,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17931,15 +17946,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONS op2 = RT_CONSTANT(opline, opline->op2); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -17948,16 +17963,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONS switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +free_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -17967,11 +17986,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONS result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -18755,8 +18775,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -18764,6 +18783,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); @@ -18772,16 +18792,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +free_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -18791,11 +18815,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 0); + 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) @@ -18809,15 +18834,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_ op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -18826,16 +18851,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_ switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +free_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -18845,11 +18874,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_ result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 0); + 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) @@ -21041,8 +21071,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -21050,6 +21079,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(1, 1); @@ -21058,16 +21088,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +free_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -21077,11 +21111,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 0); + 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) @@ -21095,15 +21130,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONS op2 = RT_CONSTANT(opline, opline->op2); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -21112,16 +21147,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONS switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +free_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -21131,11 +21170,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONS result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(result, 0); + 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) @@ -25489,8 +25529,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -25498,6 +25537,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); @@ -25506,16 +25546,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +free_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -25525,11 +25569,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -25543,15 +25588,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_ op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -25560,16 +25605,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_ switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +free_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -25579,11 +25628,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_ result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -25636,8 +25686,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -25645,6 +25694,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); @@ -25653,16 +25703,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +free_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -25672,11 +25726,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -25690,15 +25745,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_ op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -25707,16 +25762,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_ switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +free_nothrow: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -25726,11 +25785,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_ result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -37192,8 +37252,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ ZEND_VM_SMART_BRANCH(0, 1); @@ -37201,6 +37260,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ ZEND_VM_SMART_BRANCH(1, 1); @@ -37209,16 +37269,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +free_nothrow: + + + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -37228,11 +37292,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -37246,15 +37311,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST op2 = RT_CONSTANT(opline, opline->op2); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ ZEND_VM_SMART_BRANCH(0, 1); @@ -37263,16 +37328,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +free_nothrow: + + + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -37282,11 +37351,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -43747,8 +43817,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -43756,6 +43825,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); @@ -43764,16 +43834,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +free_nothrow: + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -43783,11 +43857,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -43801,15 +43876,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_H op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -43818,16 +43893,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_H switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +free_nothrow: + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -43837,11 +43916,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_H result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -43894,8 +43974,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -43903,6 +43982,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); @@ -43911,16 +43991,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +free_nothrow: + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -43930,11 +44014,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -43948,15 +44033,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_H op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); @@ -43965,16 +44050,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_H switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +free_nothrow: + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -43984,11 +44073,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_H result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -45626,8 +45716,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ ZEND_VM_SMART_BRANCH(0, 1); @@ -45635,6 +45724,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE } if (Z_TYPE_P(op1) <= IS_TRUE) { /* They are identical, return true */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ ZEND_VM_SMART_BRANCH(1, 1); @@ -45643,16 +45733,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); +free_nothrow: + + + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) == Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -45662,11 +45756,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -45680,15 +45775,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return true. Note that this has to check for undefined variable errors when IS_NULL is possible. */ - is_different_nothrow: + /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ ZEND_VM_SMART_BRANCH(1, 1); return; } if (Z_TYPE_P(op1) <= IS_TRUE) { - /* They are identical, return false */ + /* They are identical, return false. */ + /* This has to check for undefined variable errors when IS_NULL is possible. */ ZEND_VM_SMART_BRANCH(0, 1); @@ -45697,16 +45792,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA switch (Z_TYPE_P(op1)) { case IS_LONG: result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); +free_nothrow: + + + ZEND_VM_SMART_BRANCH(result, 0); break; case IS_RESOURCE: result = (Z_RES_P(op1) != Z_RES_P(op2)); break; case IS_DOUBLE: result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - break; + goto free_nothrow; case IS_STRING: result = !zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); - break; + goto free_nothrow; case IS_ARRAY: /* This may cause EG(exception) due to infinite nesting, but other zval types won't? */ /* XXX hash_zval_identical_function is not static */ @@ -45716,11 +45815,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; default: - goto is_different_nothrow; + result = 1; } + /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ - ZEND_VM_SMART_BRANCH(result, 0); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) From 2f96eba95ab752763f48ad99a3c73a2b2eb58f8d Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Mon, 11 Nov 2019 09:47:19 -0500 Subject: [PATCH 3/5] Optimize for not being indirect/undef/references Locally, I didn't see that much of a performance boost in absolute terms compared to inlining zend_is_identical (compare+unlikely jump is probably 2 instructions) --- Zend/tests/bug70785.phpt | 5 + Zend/zend_vm_def.h | 111 +++- Zend/zend_vm_execute.h | 1070 +++++++++++++++++++++++++++++++++++--- 3 files changed, 1096 insertions(+), 90 deletions(-) diff --git a/Zend/tests/bug70785.phpt b/Zend/tests/bug70785.phpt index 0a8581bd9c09..87955880e106 100644 --- a/Zend/tests/bug70785.phpt +++ b/Zend/tests/bug70785.phpt @@ -24,6 +24,11 @@ try { undefined_function(); } catch (Exception $e) { } +try { + $h !== $g; // ZEND_VM_NEXT_OPCODE + undefined_function(); +} catch (Exception $e) { +} ?> okey --EXPECT-- diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 196cb7d3854d..b6ae147d96e7 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -449,21 +449,57 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T zend_bool result; SAVE_OPLINE(); - op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); - op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); + op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); + op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); +ZEND_VM_C_LABEL(compare_values_any_type): + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((OP1_TYPE & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((OP2_TYPE & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + ZEND_VM_C_GOTO(compare_values_any_type); + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + ZEND_VM_C_GOTO(compare_values); + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((OP1_TYPE & IS_CV) && Z_ISUNDEF_P(op1)) || ((OP2_TYPE & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + ZEND_VM_C_GOTO(return_result_maythrow); + } + /* They are not identical, return false. This has to check for __destruct errors */ FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(0, 1); return; } +ZEND_VM_C_LABEL(compare_values): if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((OP1_TYPE & IS_CV) || (OP2_TYPE & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ FREE_OP1(); FREE_OP2(); - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -491,9 +527,19 @@ ZEND_VM_C_LABEL(free_nothrow): case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + ZEND_VM_C_GOTO(compare_values_any_type); + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + ZEND_VM_C_GOTO(compare_values_any_type); default: result = 1; } +ZEND_VM_C_LABEL(return_result_maythrow): /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ FREE_OP1(); FREE_OP2(); @@ -503,26 +549,61 @@ ZEND_VM_C_LABEL(free_nothrow): ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE)) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); - op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); + op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); + op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); +ZEND_VM_C_LABEL(compare_values_any_type): if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((OP1_TYPE & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((OP2_TYPE & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + ZEND_VM_C_GOTO(compare_values_any_type); + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + ZEND_VM_C_GOTO(compare_values); + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((OP1_TYPE & IS_CV) && Z_ISUNDEF_P(op1)) || ((OP2_TYPE & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + ZEND_VM_C_GOTO(return_result_maythrow); + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(1, 1); return; } +ZEND_VM_C_LABEL(compare_values): if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((OP1_TYPE & IS_CV) || (OP2_TYPE & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ FREE_OP1(); FREE_OP2(); - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -550,9 +631,19 @@ ZEND_VM_C_LABEL(free_nothrow): case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + ZEND_VM_C_GOTO(compare_values_any_type); + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + ZEND_VM_C_GOTO(compare_values_any_type); default: result = 1; } +ZEND_VM_C_LABEL(return_result_maythrow): /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ FREE_OP1(); FREE_OP2(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index f26f68286032..ddd86c688b81 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4763,19 +4763,55 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); op2 = RT_CONSTANT(opline, opline->op2); +compare_values_any_type: + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_CONST & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_CONST & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_CONST & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_CONST & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + goto return_result_maythrow; + } + /* They are not identical, return false. This has to check for __destruct errors */ ZEND_VM_SMART_BRANCH(0, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_CONST & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -4803,9 +4839,19 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ @@ -4815,26 +4861,61 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); op2 = RT_CONSTANT(opline, opline->op2); +compare_values_any_type: if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_CONST & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_CONST & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_CONST & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_CONST & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + goto return_result_maythrow; + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ ZEND_VM_SMART_BRANCH(1, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_CONST & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -4862,9 +4943,19 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_ case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ @@ -17886,19 +17977,55 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA SAVE_OPLINE(); op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); +compare_values_any_type: + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_TMP_VAR & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_CONST & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_TMP_VAR & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_CONST & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + goto return_result_maythrow; + } + /* They are not identical, return false. This has to check for __destruct errors */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(0, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_TMP_VAR & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -17926,9 +18053,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -17938,26 +18075,61 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); +compare_values_any_type: if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_TMP_VAR & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_CONST & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_TMP_VAR & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_CONST & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + goto return_result_maythrow; + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_TMP_VAR & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -17985,9 +18157,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONS case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -18774,19 +18956,55 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND SAVE_OPLINE(); op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); +compare_values_any_type: + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_TMP_VAR & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_TMP_VAR & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_TMP_VAR & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_TMP_VAR & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + goto return_result_maythrow; + } + /* They are not identical, return false. This has to check for __destruct errors */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_TMP_VAR & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -18814,9 +19032,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -18826,26 +19054,61 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); +compare_values_any_type: if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_TMP_VAR & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_TMP_VAR & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_TMP_VAR & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_TMP_VAR & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + goto return_result_maythrow; + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_TMP_VAR & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -18873,9 +19136,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_ case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -21068,21 +21341,57 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); +compare_values_any_type: + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_VAR & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_CONST & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_VAR & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_CONST & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + goto return_result_maythrow; + } + /* They are not identical, return false. This has to check for __destruct errors */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(0, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_VAR & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -21110,9 +21419,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -21122,26 +21441,61 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); +compare_values_any_type: if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_VAR & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_CONST & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_VAR & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_CONST & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + goto return_result_maythrow; + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_VAR & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -21169,9 +21523,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONS case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -25526,21 +25890,57 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); +compare_values_any_type: + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_VAR & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_TMP_VAR & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_VAR & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_TMP_VAR & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + goto return_result_maythrow; + } + /* They are not identical, return false. This has to check for __destruct errors */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_VAR & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -25568,9 +25968,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -25580,26 +25990,61 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); +compare_values_any_type: if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_VAR & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_TMP_VAR & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_VAR & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_TMP_VAR & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + goto return_result_maythrow; + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_VAR & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -25627,9 +26072,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_ case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -25683,21 +26138,57 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +compare_values_any_type: + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_VAR & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_VAR & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_VAR & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_VAR & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + goto return_result_maythrow; + } + /* They are not identical, return false. This has to check for __destruct errors */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_VAR & IS_CV) || (IS_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -25725,9 +26216,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -25737,26 +26238,61 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +compare_values_any_type: if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_VAR & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_VAR & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_VAR & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_VAR & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + goto return_result_maythrow; + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_VAR & IS_CV) || (IS_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -25784,9 +26320,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_ case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -37249,21 +37795,57 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); +compare_values_any_type: + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_CV & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_CONST & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_CV & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_CONST & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + goto return_result_maythrow; + } + /* They are not identical, return false. This has to check for __destruct errors */ ZEND_VM_SMART_BRANCH(0, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_CV & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -37291,9 +37873,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ @@ -37303,26 +37895,61 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); +compare_values_any_type: if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_CV & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_CONST & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_CV & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_CONST & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + goto return_result_maythrow; + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ ZEND_VM_SMART_BRANCH(1, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_CV & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -37350,9 +37977,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ @@ -43814,21 +44451,57 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op1 = EX_VAR(opline->op1.var); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); +compare_values_any_type: + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_CV & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_TMP_VAR & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_CV & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_TMP_VAR & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + goto return_result_maythrow; + } + /* They are not identical, return false. This has to check for __destruct errors */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_CV & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -43856,9 +44529,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -43868,26 +44551,61 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op1 = EX_VAR(opline->op1.var); op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); +compare_values_any_type: if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_CV & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_TMP_VAR & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_CV & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_TMP_VAR & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + goto return_result_maythrow; + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_CV & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -43915,9 +44633,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_H case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -43971,21 +44699,57 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + op1 = EX_VAR(opline->op1.var); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +compare_values_any_type: + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_CV & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_VAR & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_CV & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_VAR & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + goto return_result_maythrow; + } + /* They are not identical, return false. This has to check for __destruct errors */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_CV & IS_CV) || (IS_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -44013,9 +44777,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -44025,26 +44799,61 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + op1 = EX_VAR(opline->op1.var); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +compare_values_any_type: if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_CV & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_VAR & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_CV & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_VAR & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + goto return_result_maythrow; + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_CV & IS_CV) || (IS_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -44072,9 +44881,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_H case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -45713,21 +46532,57 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); +compare_values_any_type: + if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { - /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_CV & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_CV & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_CV & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_CV & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) == Z_TYPE_P(op2); + goto return_result_maythrow; + } + /* They are not identical, return false. This has to check for __destruct errors */ ZEND_VM_SMART_BRANCH(0, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_CV & IS_CV) || (IS_CV & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(1, 1); + return; + } /* They are identical, return true */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ - ZEND_VM_SMART_BRANCH(1, 1); + ZEND_VM_SMART_BRANCH(1, 0); return; } switch (Z_TYPE_P(op1)) { @@ -45755,9 +46610,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE case IS_OBJECT: result = (Z_OBJ_P(op1) == Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ @@ -45767,26 +46632,61 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; + zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); +compare_values_any_type: if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { + /* Only VAR can be indirect */ + if (UNEXPECTED(((IS_CV & IS_VAR) && Z_TYPE_P(op1) == IS_INDIRECT) || ((IS_CV & IS_VAR) && Z_TYPE_P(op2) == IS_INDIRECT))) { + ZVAL_DEINDIRECT(op1); + ZVAL_DEINDIRECT(op2); + goto compare_values_any_type; + } + /* Only VAR and CV can be references */ + if (UNEXPECTED(((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(op1)) || ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(op2)))) { + ZVAL_DEREF(op1); + ZVAL_DEREF(op2); + if (Z_TYPE_P(op1) == Z_TYPE_P(op2)) { + goto compare_values; + } + } + /* Only CV can be undef */ + if (UNEXPECTED(((IS_CV & IS_CV) && Z_ISUNDEF_P(op1)) || ((IS_CV & IS_CV) && Z_ISUNDEF_P(op2)) )) { + /* Convert undef to null, check if they're not identical */ + if (Z_TYPE_P(op1) == IS_UNDEF) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(op2) == IS_UNDEF) { + op2 = ZVAL_UNDEFINED_OP2(); + } + result = Z_TYPE_P(op1) != Z_TYPE_P(op2); + goto return_result_maythrow; + } /* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */ ZEND_VM_SMART_BRANCH(1, 1); return; } +compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { + if (((IS_CV & IS_CV) || (IS_CV & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + /* They are both undefined - fetch them to emit the undefined variable warnings. */ + op1 = ZVAL_UNDEFINED_OP1(); + op2 = ZVAL_UNDEFINED_OP2(); + ZEND_VM_SMART_BRANCH(0, 1); + return; + } /* They are identical, return false. */ - /* This has to check for undefined variable errors when IS_NULL is possible. */ + /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ - ZEND_VM_SMART_BRANCH(0, 1); + ZEND_VM_SMART_BRANCH(0, 0); return; } switch (Z_TYPE_P(op1)) { @@ -45814,9 +46714,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA case IS_OBJECT: result = (Z_OBJ_P(op1) != Z_OBJ_P(op2)); break; + case IS_REFERENCE: + /* Both are references */ + op1 = Z_REFVAL_P(op1); + op2 = Z_REFVAL_P(op2); + goto compare_values_any_type; + case IS_INDIRECT: + op1 = Z_INDIRECT_P(op1); + op2 = Z_INDIRECT_P(op2); + goto compare_values_any_type; default: result = 1; } +return_result_maythrow: /* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */ From aec0a5419eeac5e579014aea60788fdfc9cfa345 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Wed, 13 Nov 2019 08:54:54 -0500 Subject: [PATCH 4/5] Fix MacOS build error --- Zend/zend_vm_def.h | 6 ----- Zend/zend_vm_execute.h | 60 ------------------------------------------ 2 files changed, 66 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b6ae147d96e7..addc342b09f3 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -484,7 +484,6 @@ ZEND_VM_C_LABEL(compare_values_any_type): FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } ZEND_VM_C_LABEL(compare_values): if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -493,14 +492,12 @@ ZEND_VM_C_LABEL(compare_values): op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -588,7 +585,6 @@ ZEND_VM_C_LABEL(compare_values_any_type): FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } ZEND_VM_C_LABEL(compare_values): if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -597,14 +593,12 @@ ZEND_VM_C_LABEL(compare_values): op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index ddd86c688b81..36167b782286 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4796,7 +4796,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC ZEND_VM_SMART_BRANCH(0, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -4805,14 +4804,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -4900,7 +4897,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_ ZEND_VM_SMART_BRANCH(1, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -4909,14 +4905,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -18010,7 +18004,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(0, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -18019,14 +18012,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -18114,7 +18105,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONS zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(1, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -18123,14 +18113,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONS op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -18989,7 +18977,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -18998,14 +18985,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -19093,7 +19078,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -19102,14 +19086,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -21376,7 +21358,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(0, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -21385,14 +21366,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -21480,7 +21459,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONS zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(1, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -21489,14 +21467,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONS op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -25925,7 +25901,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -25934,14 +25909,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -26029,7 +26002,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -26038,14 +26010,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -26173,7 +26143,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -26182,14 +26151,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -26277,7 +26244,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -26286,14 +26252,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -37830,7 +37794,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN ZEND_VM_SMART_BRANCH(0, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -37839,14 +37802,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -37934,7 +37895,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST ZEND_VM_SMART_BRANCH(1, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -37943,14 +37903,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -44486,7 +44444,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -44495,14 +44452,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -44590,7 +44545,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_H zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -44599,14 +44553,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_H op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -44734,7 +44686,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -44743,14 +44694,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -44838,7 +44787,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_H zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(1, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -44847,14 +44795,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_H op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -46567,7 +46513,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE ZEND_VM_SMART_BRANCH(0, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -46576,14 +46521,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(1, 1); - return; } /* They are identical, return true */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ ZEND_VM_SMART_BRANCH(1, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: @@ -46671,7 +46614,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA ZEND_VM_SMART_BRANCH(1, 1); - return; } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { @@ -46680,14 +46622,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); ZEND_VM_SMART_BRANCH(0, 1); - return; } /* They are identical, return false. */ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */ ZEND_VM_SMART_BRANCH(0, 0); - return; } switch (Z_TYPE_P(op1)) { case IS_LONG: From 18a672b8bb72f685231b474cea4e7516629a6437 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Wed, 13 Nov 2019 16:41:05 -0500 Subject: [PATCH 5/5] Fix undefined zval check --- Zend/zend_vm_def.h | 4 ++-- Zend/zend_vm_execute.h | 40 ++++++++++++++++++++-------------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index addc342b09f3..ef2ad13ea9aa 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -487,7 +487,7 @@ ZEND_VM_C_LABEL(compare_values_any_type): } ZEND_VM_C_LABEL(compare_values): if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((OP1_TYPE & IS_CV) || (OP2_TYPE & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((OP1_TYPE & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((OP2_TYPE & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -588,7 +588,7 @@ ZEND_VM_C_LABEL(compare_values_any_type): } ZEND_VM_C_LABEL(compare_values): if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((OP1_TYPE & IS_CV) || (OP2_TYPE & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((OP1_TYPE & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((OP2_TYPE & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 36167b782286..dea202202969 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4799,7 +4799,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_CONST & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_CONST & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_CONST & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -4900,7 +4900,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_ } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_CONST & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_CONST & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_CONST & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -18007,7 +18007,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_TMP_VAR & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_TMP_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_CONST & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -18108,7 +18108,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONS } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_TMP_VAR & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_TMP_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_CONST & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -18980,7 +18980,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_TMP_VAR & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_TMP_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_TMP_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -19081,7 +19081,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_ } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_TMP_VAR & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_TMP_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_TMP_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -21361,7 +21361,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_VAR & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_CONST & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -21462,7 +21462,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONS } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_VAR & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_CONST & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -25904,7 +25904,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_VAR & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_TMP_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -26005,7 +26005,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_ } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_VAR & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_TMP_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -26146,7 +26146,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_VAR & IS_CV) || (IS_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -26247,7 +26247,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_ } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_VAR & IS_CV) || (IS_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -37797,7 +37797,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_CV & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_CV & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_CONST & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -37898,7 +37898,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_CV & IS_CV) || (IS_CONST & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_CV & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_CONST & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -44447,7 +44447,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_CV & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_CV & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_TMP_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -44548,7 +44548,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_H } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_CV & IS_CV) || (IS_TMP_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_CV & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_TMP_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -44689,7 +44689,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_CV & IS_CV) || (IS_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_CV & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -44790,7 +44790,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_H } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_CV & IS_CV) || (IS_VAR & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_CV & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_VAR & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -46516,7 +46516,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_CV & IS_CV) || (IS_CV & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_CV & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_CV & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2(); @@ -46617,7 +46617,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA } compare_values: if (Z_TYPE_P(op1) <= IS_TRUE) { - if (((IS_CV & IS_CV) || (IS_CV & IS_CV)) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + if (((IS_CV & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) || ((IS_CV & IS_CV) && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF))) { /* They are both undefined - fetch them to emit the undefined variable warnings. */ op1 = ZVAL_UNDEFINED_OP1(); op2 = ZVAL_UNDEFINED_OP2();